Mysql
 sql >> база данни >  >> RDS >> Mysql

По-добре разберете проблемите на SQLalchemy `yield_per()`

И двете проблемни стратегии за зареждане предизвикват изключения, ако се опитате да ги използвате с yield_per , така че всъщност не е нужно да се тревожите твърде много.

Вярвам единственият проблем с subqueryload е, че груповото зареждане на втората заявка не е реализирано (все още). Нищо няма да се обърка семантично, но ако използвате yield_per , вероятно имате наистина добра причина да не искате да зареждате всички резултати наведнъж. Така че SQLAlchemy учтиво отказва да противоречи на вашите желания.

joinedload е малко по-фин. Забранено е само в случай на колекция, където основният ред може да има множество асоциирани реда. Да кажем, че вашата заявка дава необработени резултати като този, където A и B са първични ключове от различни таблици:

 A | B 
---+---
 1 | 1 
 1 | 2 
 1 | 3 
 1 | 4 
 2 | 5 
 2 | 6 

Сега ги извличате с yield_per(3) . Проблемът е, че SQLAlchemy може да ограничи само колко извлича по редове , но трябва да върне обекти . Тук SQLAlchemy вижда само първите три реда, така че създава A обект с ключ 1 и три B деца:1, 2 и 3.

Когато зареди следващата партида, иска да създаде нов A обект с ключ 1... а, но той вече има един от тях, така че няма нужда да го създавате отново. Допълнителният B , 4, се губи. (Така че, не, дори четене на присъединени колекции с yield_per не е безопасно — парчета от вашите данни може да изчезнат.)

Може да кажете „е, просто продължете да четете редове, докато имате пълен обект“ – но какво ще стане, ако това A има сто деца? Или милион? SQLAlchemy не може разумно да гарантира, че може да направи това, което поискате и дава правилни резултати, така че отказва да опита.

Не забравяйте, че DBAPI е проектиран така, че всякакъв базата данни може да се използва със същия API, дори ако тази база данни не поддържа всички функции на DBAPI. Имайте предвид, че DBAPI е проектиран около курсори, но MySQL всъщност не има курсори! Вместо това DBAPI адаптерите за MySQL трябва да ги фалшифицират.

Така че докато cursor.fetchmany(100) ще работи , можете да видите от MySQLdb изходен код че не извлича мързеливо от сървъра; извлича всичко в един голям списък, след което връща парче, когато извикате fetchmany .

Какво psycopg2 supports е истинско поточно предаване, при което резултатите се запомнят постоянно на сървъра и вашият Python процес вижда само няколко от тях наведнъж.

Все още можете да използвате yield_per с MySQLdb , или всеки друг DBAPI; това е целият смисъл на дизайна на DBAPI. Ще трябва да платите разходите за памет за всички сурови редове, скрити в DBAPI (които са кортежи, доста евтини), но няма също трябва да плащате за всички ORM обекти едновременно.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL диакритично нечувствително търсене (арабски)

  2. MySQL Изтрийте всички редове от таблицата и нулирайте ID на нула

  3. Правилно индексиране при използване на оператор ИЛИ

  4. Най-бързият начин за изхвърляне на обект от речник на Python (dict) в MySQL таблица?

  5. Как да напиша php файл за показване на изображение като <img src=/img.php?imageID=32 />?