Python 最常見的 ORM package - SQLAlchemy 使用了 relationship 將多個 Model 關聯起來。在使用上會發現有一個 lazy
的參數
lazy 這個設定主要是設定,其關聯的 Model 要使用何種方式來載入,以下為其值:
True
&select
:當要 access 該屬性時,會使用SELECT
條件來去取得資料。適用於 many-to-one 的關聯False
&joined
:當要 access 該屬性時,會使用JOIN
或LEFT OUTER JOIN
條件來去取得資料。至於是否使用 "outer" 則取決於relationship.innerjoin
參數。適合用於使用 parent 時會頻繁用到相關聯的 model 的情況,屬於 "eager loading"(立即載入) 的範疇。None
&noload
:任何時候都不載入。只為了支援 "write-only" 屬性immediate
:當 parent 在載入時也一併使用SELECT
將資料載入。適用於 many-to-one 的關聯subquery
:屬於 "eager loading"(立即載入) 的範疇,與joined
的使用情境相似。會使用一個額外的 SQL,使用 subquery 後再將結果用JOIN
結合。當 "many" 方資料較大時,建議使用,資料較小就是使用 joined。缺點是,當查詢數量超過 500 則建議使用selectin
更適合。>> user = session.query(User).first() SELECT user_address.id AS user_address_id, user_address.address AS user_address_address, user_address.user_id AS user_address_user_id, anon_1.user_id AS anon_1_user_id FROM (SELECT user.id AS user_id FROM user LIMIT ? offset ?) AS anon_1 JOIN user_address ON anon_1.user_id = user_address.user_id ORDER BY anon_1.user_id
selectin
:屬於 "eager loading"(立即載入) 的範疇,適合用於使用 parent 時會頻繁用到相關聯的 model 的情況。使用一個或多個額外的 SQL,並使用 JOIN 到即時的 parent 物件。其中 primary key 是使用了IN
來篩選。類似於subquery
,但他會更簡單、可快取且高效的 SQL。raise
:不允許 lazy loading。如果其 value 不能透過 eager loading,將會報錯InvalidRequestError
。raise_on_sql
:dynamic
:在訪問屬性的時候,並不會載入,而是回傳一個 query。需要額外去執行相對應的方法才可以得到資料。適用於資料量大的時候,因為還能對其做filter()
。
結論
從資料量大到小的排序的話:
dynamic > selectin > subquery > joined > select > immediate
如果加上使用的頻繁高到低排序: (會將 eager loading 放到前面)
selectin > subquery > joined > immediate > select > dynamic