De meeste DBAPI-implementaties bufferen rijen volledig als ze worden opgehaald - dus meestal, voordat de SQLAlchemy ORM zelfs maar één resultaat krijgt, is de hele resultatenset in het geheugen.
Maar dan, de manier waarop Query
werkt, is dat het de gegeven resultatenset standaard volledig laadt voordat u uw objecten terugstuurt. De grondgedachte hier betreft query's die meer zijn dan eenvoudige SELECT-instructies. Bijvoorbeeld, in joins met andere tabellen die dezelfde objectidentiteit meerdere keren in één resultaatset kunnen retourneren (gebruikelijk bij enthousiast laden), moet de volledige set rijen in het geheugen staan, zodat de juiste resultaten kunnen worden geretourneerd, anders collecties en dergelijke is mogelijk slechts gedeeltelijk bevolkt.
Dus Query
biedt een optie om dit gedrag te wijzigen via yield_per()
. Deze aanroep veroorzaakt de Query
om rijen in batches op te leveren, waar u het de batchgrootte geeft. Zoals de documenten stellen, is dit alleen geschikt als je niet gretig bezig bent met het laden van collecties, dus het is eigenlijk als je echt weet wat je doet. Als de onderliggende DBAPI rijen pre-buffert, zal er nog steeds die geheugenoverhead zijn, dus de aanpak schaalt maar iets beter dan het niet gebruiken ervan.
Ik gebruik zelden yield_per()
; in plaats daarvan gebruik ik een betere versie van de LIMIT-aanpak die je hierboven voorstelt met behulp van vensterfuncties. LIMIT en OFFSET hebben een enorm probleem dat zeer grote OFFSET-waarden ervoor zorgen dat de query langzamer en langzamer wordt, omdat een OFFSET van N ervoor zorgt dat deze door N rijen bladert - het is alsof dezelfde query vijftig keer wordt uitgevoerd in plaats van één, elke keer dat een groter en groter aantal rijen. Met een venster-functiebenadering haal ik vooraf een set "venster" -waarden op die verwijzen naar delen van de tabel die ik wil selecteren. Ik zend vervolgens individuele SELECT-instructies uit die elk uit een van die vensters tegelijk worden gehaald.
De benadering van de vensterfunctie is op de wiki en ik gebruik het met veel succes.
Let ook op:niet alle databases ondersteunen vensterfuncties; je hebt Postgresql, Oracle of SQL Server nodig. IMHO is het gebruik van ten minste Postgresql zeker de moeite waard - als je een relationele database gebruikt, kun je net zo goed de beste gebruiken.