Sqlalchemy-orm-eager-loading

提供:Dev Guides
移動先:案内検索

SQLAlchemy ORM-Eager Loading

負荷が大きいと、クエリの数が減ります。 SQLAlchemyは、クエリに追加の指示を与えるクエリオプションを介して呼び出される積極的な読み込み関数を提供します。 これらのオプションは、Query.options()メソッドを介してさまざまな属性をロードする方法を決定します。

サブクエリロード

Customer.invoicesを熱心にロードする必要があります。 orm.subqueryload()オプションは、ロードしたばかりの結果に関連付けられたコレクションを完全にロードする2番目のSELECTステートメントを提供します。 「subquery」という名前により、SELECTステートメントは、再利用されたクエリを介して直接構築され、関連テーブルに対するSELECTへのサブクエリとして埋め込まれます。

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

これは、次の2つの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',)

2つのテーブルからデータにアクセスするには、以下のプログラムを使用することができます-

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

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

上記のプログラムの出力は次のとおりです-

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

結合荷重

他の関数はorm.joinedload()と呼ばれます。 これにより、LEFT OUTER JOINが発行されます。 リードオブジェクトと関連オブジェクトまたはコレクションが1ステップでロードされます。

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

これは、上記と同じ出力を与える次の式を出力します-

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

OUTER JOINは2行になりましたが、Customerのインスタンスを1つ返します。 これは、Queryが、返されたエンティティにオブジェクトIDに基づいて「一意」戦略を適用するためです。 クエリ結果に影響を与えることなく、結合されたイーガーロードを適用できます。

関連クエリのロードにはsubqueryload()の方が適していますが、joinedload()は多対1の関係に適しています。