Obie problematyczne strategie ładowania powodują wyjątki, jeśli spróbujesz ich użyć z yield_per
, więc naprawdę nie musisz się zbytnio martwić.
wierzę jedyny problem z podzapytanie
jest to, że ładowanie wsadowe drugiego zapytania nie jest (jeszcze) zaimplementowane. Nic nie poszłoby źle semantycznie, ale jeśli używasz yield_per
, prawdopodobnie masz naprawdę dobry powód, aby nie chcieć wczytywać wszystkich wyników jednocześnie. Więc SQLAlchemy grzecznie odmawia działania wbrew twoim życzeniom.
dołączyło
jest trochę bardziej subtelny. Jest to zabronione tylko w przypadku kolekcji, w której wiersz podstawowy może mieć wiele powiązanych wierszy. Załóżmy, że zapytanie daje nieprzetworzone wyniki takie jak ten, gdzie A i B to klucze podstawowe z różnych tabel:
A | B
---+---
1 | 1
1 | 2
1 | 3
1 | 4
2 | 5
2 | 6
Teraz pobierasz je za pomocą yield_per(3)
. Problem polega na tym, że SQLAlchemy może ograniczać ilość pobieranych danych za pomocą wierszy , ale musi zwracać obiekty . Tutaj SQLAlchemy widzi tylko pierwsze trzy wiersze, więc tworzy A
obiekt z kluczem 1 i trzy B
dzieci:1, 2 i 3.
Kiedy ładuje następną partię, chce utworzyć nowy A
obiekt z kluczem 1... ach, ale ma już jeden z nich, więc nie ma potrzeby tworzenia go ponownie. Dodatkowe B
, 4, jest stracone. (Więc nie, nawet czytanie połączonych kolekcji za pomocą yield_per
jest niebezpieczne — mogą zniknąć fragmenty Twoich danych.)
Możesz powiedzieć „cóż, po prostu czytaj dalej wiersze, aż uzyskasz pełny obiekt” — ale co, jeśli ten A
ma setkę dzieci? Albo milion? SQLAlchemy nie może zagwarantować, że wykona to, o co prosiłeś i daje prawidłowe wyniki, więc odmawia prób.
Pamiętaj, że DBAPI jest zaprojektowane tak, aby dowolne bazy danych można używać z tym samym interfejsem API, nawet jeśli ta baza danych nie obsługuje wszystkich funkcji DBAPI. Weź pod uwagę, że DBAPI jest zaprojektowane wokół kursorów, ale MySQL tak naprawdę nie ma kursory! Zamiast tego adaptery DBAPI dla MySQL muszą je fałszować.
Więc podczas gdy cursor.fetchmany(100)
będzie działać , możesz zobaczyć z MySQLdb kod źródłowy
że nie pobiera leniwie z serwera; pobiera wszystko do jednej dużej listy, a następnie zwraca wycinek, gdy wywołasz fetchmany
.
Co psycopg2
obsługuje prawdziwe strumieniowanie, w którym wyniki są zapamiętywane na stałe na serwerze, a Twój proces Pythona widzi tylko kilka z nich na raz.
Nadal możesz używać yield_per
z MySQLdb
, lub jakikolwiek inny DBAPI; to jest cały punkt projektu DBAPI. Będziesz musiał zapłacić koszt pamięci za wszystkie nieprzetworzone wiersze ukryte w DBAPI (które są krotkami, dość tanie), ale nie również zapłacić za wszystkie obiekty ORM w tym samym czasie.