SQLAlchemy ORM - Zachłanne ładowanie

Chętne ładowanie zmniejsza liczbę zapytań. SQLAlchemy oferuje funkcje szybkiego ładowania wywoływane przez opcje zapytania, które dają dodatkowe instrukcje zapytaniu. Te opcje określają sposób ładowania różnych atrybutów za pomocą metody Query.options ().

Ładowanie podzapytania

Chcemy, aby faktury Klienta były szybko ładowane. Opcja orm.subqueryload () daje drugą instrukcję SELECT, która w pełni ładuje kolekcje powiązane z właśnie załadowanymi wynikami. Nazwa „podzapytanie” powoduje, że instrukcja SELECT jest konstruowana bezpośrednio przez zapytanie ponownie użyte i osadzone jako podzapytanie w SELECT względem powiązanej tabeli.

from sqlalchemy.orm import subqueryload
c1 = session.query(Customer).options(subqueryload(Customer.invoices)).filter_by(name = 'Govind Pant').one()

Powoduje to dwa następujące wyrażenia SQL -

SELECT customers.id 
AS customers_id, customers.name 
AS customers_name, customers.address 
AS customers_address, customers.email 
AS customers_email
FROM customers
WHERE customers.name = ?
('Govind Pant',)

SELECT invoices.id 
AS invoices_id, invoices.custid 
AS invoices_custid, invoices.invno 
AS invoices_invno, invoices.amount 
AS invoices_amount, anon_1.customers_id 
AS anon_1_customers_id
FROM (
   SELECT customers.id 
   AS customers_id
   FROM customers
   WHERE customers.name = ?) 
   
AS anon_1 
JOIN invoices 
ON anon_1.customers_id = invoices.custid 
ORDER BY anon_1.customers_id, invoices.id 2018-06-25 18:24:47,479 
INFO sqlalchemy.engine.base.Engine ('Govind Pant',)

Aby uzyskać dostęp do danych z dwóch tabel, możemy skorzystać z poniższego programu -

print (c1.name, c1.address, c1.email)

for x in c1.invoices:
   print ("Invoice no : {}, Amount : {}".format(x.invno, x.amount))

Wynik powyższego programu jest następujący -

Govind Pant Gulmandi Aurangabad [email protected]
Invoice no : 3, Amount : 10000
Invoice no : 4, Amount : 5000

Połączone obciążenie

Druga funkcja nazywa się orm.joinedload (). To emituje LEWE POŁĄCZENIE ZEWNĘTRZNE. Obiekt wiodący oraz powiązany obiekt lub kolekcja są ładowane w jednym kroku.

from sqlalchemy.orm import joinedload
c1 = session.query(Customer).options(joinedload(Customer.invoices)).filter_by(name='Govind Pant').one()

To emituje następujące wyrażenie dające taki sam wynik jak powyżej -

SELECT customers.id 
AS customers_id, customers.name 
AS customers_name, customers.address 
AS customers_address, customers.email 
AS customers_email, invoices_1.id 
AS invoices_1_id, invoices_1.custid 
AS invoices_1_custid, invoices_1.invno 
AS invoices_1_invno, invoices_1.amount 
AS invoices_1_amount

FROM customers 
LEFT OUTER JOIN invoices 
AS invoices_1 
ON customers.id = invoices_1.custid

WHERE customers.name = ? ORDER BY invoices_1.id
('Govind Pant',)

ZEWNĘTRZNE JOIN spowodowało powstanie dwóch wierszy, ale zwraca jedno wystąpienie klienta. Dzieje się tak, ponieważ Query stosuje strategię „unikatową”, opartą na tożsamości obiektu, do zwracanych jednostek. Dołączone przyspieszone ładowanie można zastosować bez wpływu na wyniki zapytania.

Subqueryload () jest bardziej odpowiednia do ładowania powiązanych kolekcji, podczas gdy joinload () lepiej nadaje się do relacji wiele do jednego.