Většina implementací DBAPI plně ukládá řádky do paměti, když jsou načítány - takže obvykle, než SQLAlchemy ORM vůbec zadrží jeden výsledek, je celá sada výsledků v paměti.
Ale pak způsob Query
funguje tak, že ve výchozím nastavení plně načte danou sadu výsledků, než vám vrátí vaše objekty. Odůvodnění se týká dotazů, které jsou více než jednoduchými příkazy SELECT. Například u spojení s jinými tabulkami, které mohou v jedné sadě výsledků vracet stejnou identitu objektu vícekrát (běžné s dychtivým načítáním), musí být v paměti celá sada řádků, aby bylo možné vrátit správné výsledky, jinak kolekce a podobně může být obsazeno pouze částečně.
Takže Query
nabízí možnost změnit toto chování prostřednictvím yield_per()
. Toto volání způsobí Query
k získání řádků v dávkách, kde uvedete velikost dávky. Jak je uvedeno v dokumentech, je to vhodné pouze v případě, že neprovádíte žádné horlivé načítání sbírek, takže v zásadě jde o to, pokud opravdu víte, co děláte. Také, pokud podkladové DBAPI předvyrovnávací paměti řádky, bude stále existovat tato paměťová režie, takže přístup je jen o něco lepší, než když jej nepoužíváte.
Téměř nikdy nepoužívám yield_per()
; místo toho používám lepší verzi přístupu LIMIT, který navrhujete výše, pomocí funkcí okna. LIMIT a OFFSET mají obrovský problém v tom, že velmi velké hodnoty OFFSET způsobují, že se dotaz zpomaluje a zpomaluje, protože OFFSET N způsobí, že listuje N řádků - je to jako dělat stejný dotaz padesátkrát místo jednoho, pokaždé, když čtete větší a větší počet řádků. S přístupem funkce okna předem načítám sadu hodnot „okna“, které odkazují na části tabulky, které chci vybrat. Poté vygeneruji jednotlivé příkazy SELECT, které každý vytáhne z jednoho z těchto oken najednou.
Přístup k funkci okna je na wiki a používám jej s velkým úspěchem.
Poznámka:ne všechny databáze podporují funkce oken; potřebujete Postgresql, Oracle nebo SQL Server. IMHO používat alespoň Postgresql se rozhodně vyplatí – pokud používáte relační databázi, můžete také použít tu nejlepší.