Obě problematické strategie načítání vyvolávají výjimky, pokud se je pokusíte použít s yield_per
, takže se opravdu nemusíte příliš bát.
Věřím jediný problém s subqueryload
je, že dávkové načítání druhého dotazu není (zatím) implementováno. Sémanticky by se nic nepokazilo, ale pokud používáte yield_per
, pravděpodobně máte opravdu dobrý důvod, proč nechcete načítat všechny výsledky najednou. Takže SQLAlchemy zdvořile odmítá jít proti vašemu přání.
joinedload
je trochu jemnější. Je zakázáno pouze v případě kolekce, kde může mít primární řádek více přidružených řádků. Řekněme, že váš dotaz poskytuje nezpracované výsledky, jako je tento, kde A a B jsou primární klíče z různých tabulek:
A | B
---+---
1 | 1
1 | 2
1 | 3
1 | 4
2 | 5
2 | 6
Nyní je získáte pomocí yield_per(3)
. Problém je v tom, že SQLAlchemy může omezit načítání pouze podle řádků , ale musí vrátit objekty . Zde SQLAlchemy vidí pouze první tři řádky, takže vytvoří A
objekt s klíčem 1 a tři B
děti:1, 2 a 3.
Když načte další dávku, chce vytvořit nový A
objekt s klíčem 1... ach, ale jeden z nich již má, takže jej není třeba znovu vytvářet. Extra B
, 4, je ztracen. (Takže ne, dokonce i čtení spojených kolekcí s yield_per
je nebezpečné – části vašich dat mohou zmizet.)
Můžete říct „no, jen čtěte řádky, dokud nebudete mít celý objekt“ — ale co když to A
má sto dětí? Nebo milion? SQLAlchemy nemůže rozumně zaručit, že dokáže to, co jste požadovali a produkovat správné výsledky, takže to odmítne zkusit.
Pamatujte, že DBAPI je navrženo tak, aby jakékoli databázi lze použít se stejným API, i když tato databáze nepodporuje všechny funkce DBAPI. Vezměte v úvahu, že DBAPI je navrženo pro kurzory, ale MySQL ve skutečnosti nemá kurzory! Adaptéry DBAPI pro MySQL je musí místo toho podvrhnout.
Takže zatímco cursor.fetchmany(100)
bude fungovat , můžete vidět z MySQLdb
zdrojový kód
že se ze serveru nestahuje líně; načte vše do jednoho velkého seznamu a poté, když zavoláte fetchmany
, vrátí řez .
Co psycopg2
podporuje je true streaming, kde jsou výsledky zapamatovány trvale na serveru a váš proces Python jich vidí najednou jen několik.
Stále můžete použít yield_per
pomocí MySQLdb
nebo jakékoli jiné DBAPI; to je celý smysl návrhu DBAPI. Budete muset zaplatit náklady na paměť za všechny nezpracované řádky skryté v DBAPI (což jsou n-tice, poměrně levné), ale nebudete také musí platit za všechny objekty ORM současně.