La maggior parte delle implementazioni DBAPI bufferizza completamente le righe man mano che vengono recuperate, quindi di solito, prima che l'ORM SQLAlchemy ottenga anche solo un risultato, l'intero set di risultati è in memoria.
Ma poi, il modo in cui Query
funziona è che carica completamente il set di risultati specificato per impostazione predefinita prima di restituirti i tuoi oggetti. La logica qui riguarda le query che sono più che semplici istruzioni SELECT. Ad esempio, nei join ad altre tabelle che possono restituire la stessa identità dell'oggetto più volte in un set di risultati (comune con il caricamento ansioso), il set completo di righe deve essere in memoria in modo che i risultati corretti possano essere restituiti altrimenti raccolte e simili potrebbe essere popolato solo parzialmente.
Quindi Query
offre un'opzione per modificare questo comportamento yield_per()
. Questa chiamata farà sì che il Query
produca righe in batch, dove gli dai la dimensione del batch. Come affermano i documenti, questo è appropriato solo se non stai facendo alcun tipo di caricamento desideroso delle raccolte, quindi è fondamentalmente se sai davvero cosa stai facendo. Inoltre, se il DBAPI sottostante esegue il pre-buffer delle righe, ci sarà ancora quel sovraccarico di memoria, quindi l'approccio si ridimensiona solo leggermente meglio rispetto al mancato utilizzo.
Non lo uso quasi mai yield_per()
; invece, utilizzo una versione migliore dell'approccio LIMIT che suggerisci sopra usando le funzioni della finestra. LIMIT e OFFSET hanno un grosso problema che valori di OFFSET molto grandi fanno sì che la query diventi sempre più lenta, poiché un OFFSET di N fa sì che si sfoglia N righe - è come fare la stessa query cinquanta volte invece di una, ogni volta che legge un numero sempre maggiore di righe. Con un approccio basato sulla funzione finestra, prelevo un insieme di valori "finestra" che si riferiscono a parti della tabella che desidero selezionare. Quindi emetto singole istruzioni SELECT che ciascuna estrae da una di quelle finestre alla volta.
L'approccio alla funzione finestra è sul wiki e lo uso con grande successo.
Nota anche: non tutti i database supportano le funzioni della finestra; hai bisogno di Postgresql, Oracle o SQL Server. IMHO usando almeno Postgresql ne vale sicuramente la pena: se stai usando un database relazionale, potresti anche usare il meglio.