sql >> Databáze >  >> RDS >> Mysql

Lepší pochopení problémů SQLalchemy s `yield_per()`

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ě.



  1. Jak používat sloupec temp v klauzuli where

  2. Jak se vyhnout opravě pomocí Keycache?

  3. Jak mohu získat počet dní mezi 2 daty v Oracle 11g?

  4. Funkce COUNT() v MariaDB