SQLAlchemy ORM - Eifriges Laden

Eifrige Last reduziert die Anzahl der Abfragen. SQLAlchemy bietet eifrige Ladefunktionen, die über Abfrageoptionen aufgerufen werden und der Abfrage zusätzliche Anweisungen geben. Diese Optionen bestimmen, wie verschiedene Attribute über die Query.options () -Methode geladen werden.

Unterabfrage laden

Wir möchten, dass Customer.invoices eifrig geladen werden. Die Option orm.subqueryload () gibt eine zweite SELECT-Anweisung aus, die die Sammlungen, die den gerade geladenen Ergebnissen zugeordnet sind, vollständig lädt. Der Name "Unterabfrage" bewirkt, dass die SELECT-Anweisung direkt über die wiederverwendete Abfrage erstellt und als Unterabfrage in eine SELECT für die zugehörige Tabelle eingebettet wird.

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

Dies führt zu den folgenden zwei SQL-Ausdrücken:

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',)

Um auf die Daten aus zwei Tabellen zuzugreifen, können wir das folgende Programm verwenden:

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

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

Die Ausgabe des obigen Programms ist wie folgt:

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

Verbundenes Laden

Die andere Funktion heißt orm.joinedload (). Dies gibt einen LEFT OUTER JOIN aus. Das Hauptobjekt sowie das zugehörige Objekt oder die zugehörige Sammlung werden in einem Schritt geladen.

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

Dies gibt den folgenden Ausdruck aus, der dieselbe Ausgabe wie oben ergibt -

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',)

Der OUTER JOIN führte zu zwei Zeilen, gibt jedoch eine Instanz des Kunden zurück. Dies liegt daran, dass Query eine auf der Objektidentität basierende "Eindeutigkeits" -Strategie auf die zurückgegebenen Entitäten anwendet. Verbundenes eifriges Laden kann angewendet werden, ohne die Abfrageergebnisse zu beeinflussen.

Subqueryload () eignet sich besser zum Laden verwandter Sammlungen, während joinload () besser für die Beziehung zwischen vielen Personen geeignet ist.