Kortom, de standaardstrategie van oracle voor recente ojdbc-jars is om een array vooraf toe te wijzen per "prefetch"-rij die geschikt is voor de grootst denkbare grootte die mogelijk is om uit die query te retourneren. Voor alle rijen. Dus in mijn geval had ik daar wat VARCHAR2 (4000) in, en 50 threads (Statements) * 3 kolommen van varchar2's * 4000 waren opgeteld tot meer dan gigabytes RAM met een setFetchSize van een paar honderd [yikes]. Er lijkt geen optie te zijn om te zeggen "geef die array niet vooraf toe, gebruik gewoon de grootte zoals ze binnenkomen." Ojdbc houdt deze vooraf toegewezen buffers zelfs rond tussen voorbereide verklaringen (cached/verbinding) zodat het ze opnieuw kan gebruiken. Absoluut een geheugenzwijn.
Een tijdelijke oplossing:gebruik setFetchSize
tot een redelijk bedrag. De standaardwaarde is 10, wat vrij traag kan zijn bij verbindingen met een hoge latentie. Maak een profiel en gebruik alleen de hoogste setFetchSize die daadwerkelijk significante snelheidsverbeteringen oplevert.
Een andere oplossing is om de maximale werkelijke kolomgrootte te bepalen en de query vervolgens te vervangen door (ervan uitgaande dat 50 de bekende maximale werkelijke grootte is) select substr(column_name, 0, 50)
Andere dingen die u kunt doen:verminder het aantal prefetch-rijen, verhoog java -Xmx
parameter, selecteert u alleen de kolommen die u echt nodig heeft.
Toen we eenmaal in staat waren om ten minste prefetch 400 te gebruiken [zorg ervoor dat u een profiel maakt om te zien welke nummers goed voor u zijn, met hoge latentie zagen we verbeteringen tot een prefetch-grootte van 3-4K] voor alle query's, de prestaties verbeterden drastisch.
Ik veronderstel dat als je echt agressief wilt zijn tegen schaarse "echt lange" rijen, je misschien opnieuw een query kunt uitvoeren als je deze [zeldzame] grote rijen tegenkomt.
Details advertentie nauseum hier