De fleste DBAPI-implementeringer bufferrækker fuldt ud, efterhånden som de hentes - så normalt, før SQLAlchemy ORM overhovedet får fat i ét resultat, er hele resultatsættet i hukommelsen.
Men altså, måden Query
på fungerer, er, at det indlæser det givne resultatsæt som standard fuldt ud, før det returnerer dine objekter til dig. Begrundelsen her vedrører forespørgsler, der er mere end simple SELECT-sætninger. For eksempel, i joins til andre tabeller, der kan returnere den samme objektidentitet flere gange i ét resultatsæt (almindelig med ivrig indlæsning), skal det fulde sæt af rækker være i hukommelsen, så de korrekte resultater kan returneres ellers samlinger og lignende er muligvis kun delvist udfyldt.
Så Query
tilbyder en mulighed for at ændre denne adfærd gennem yield_per()
. Dette opkald vil forårsage Query
at give rækker i partier, hvor man giver den batchstørrelsen. Som dokumenterne siger, er dette kun passende, hvis du ikke laver nogen form for ivrig indlæsning af samlinger, så det er dybest set, hvis du virkelig ved, hvad du laver. Hvis de underliggende DBAPI-præ-buffere rækker, vil der stadig være hukommelsesoverhead, så tilgangen skaleres kun lidt bedre end ikke at bruge den.
Jeg bruger næsten aldrig yield_per()
; i stedet bruger jeg en bedre version af den LIMIT-tilgang, du foreslår ovenfor, ved at bruge vinduesfunktioner. LIMIT og OFFSET har et stort problem, at meget store OFFSET-værdier får forespørgslen til at blive langsommere og langsommere, da en OFFSET på N får den til at bladre gennem N rækker - det er som at gøre den samme forespørgsel halvtreds gange i stedet for én, hver gang man læser en større og større antal rækker. Med en vinduesfunktionstilgang på forhånd henter jeg et sæt "vindue"-værdier, der refererer til bidder af den tabel, jeg vil vælge. Jeg udsender derefter individuelle SELECT-sætninger, som hver trækker fra et af disse vinduer ad gangen.
Vinduesfunktionstilgangen er på wikien og jeg bruger det med stor succes.
Bemærk også:ikke alle databaser understøtter vinduesfunktioner; du skal bruge Postgresql, Oracle eller SQL Server. IMHO ved at bruge mindst Postgresql er bestemt det værd - hvis du bruger en relationel database, kan du lige så godt bruge den bedste.