Mysql
 sql >> Database >  >> RDS >> Mysql

iteratore/generatore SqlAlchemy integrato a basso consumo di memoria?

La maggior parte delle implementazioni DBAPI memorizza completamente le righe man mano che vengono recuperate, quindi di solito, prima ancora che SQLAlchemy ORM ottenga un blocco di un risultato, l'intero set di risultati è in memoria.

Ma poi, il modo in cui Query funziona è che carica completamente il set di risultati fornito 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), l'intero set di righe deve essere in memoria in modo che i risultati corretti possano essere restituiti altrimenti raccolte e simili potrebbe essere solo parzialmente popolato.

Quindi Query offre un'opzione per modificare questo comportamento tramite yield_per() . Questa chiamata provocherà la Query per produrre righe in batch, dove gli dai la dimensione del batch. Come affermano i documenti, questo è appropriato solo se non stai eseguendo alcun tipo di caricamento ansioso di raccolte, quindi è fondamentalmente se sai davvero cosa stai facendo. Inoltre, se le righe pre-buffer DBAPI sottostanti, ci sarà ancora quell'overhead di memoria, quindi l'approccio si ridimensiona solo leggermente meglio rispetto al non usarlo.

Non 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 OFFSET molto grandi fanno sì che la query diventi sempre più lenta, poiché un OFFSET di N fa scorrere N righe:è come eseguire la stessa query cinquanta volte invece di una, ogni volta leggendo un numero sempre maggiore di righe. Con un approccio alla funzione finestra, prelevo una serie di valori "finestra" che si riferiscono a blocchi della tabella che voglio selezionare. Quindi emetto singole istruzioni SELECT che ciascuna estrae da una di quelle finestre alla volta.

L'approccio della funzione finestra è sul wiki e lo uso con grande successo.

Nota inoltre:non tutti i database supportano le funzioni delle finestre; 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.