3 回答

TA貢獻1803條經驗 獲得超3個贊
兩種方法可以達到相同的目的,從而放棄不必要的數據庫查詢。但是他們使用不同的方法來提高效率。
使用這兩種方法的唯一原因是,當單個大型查詢優于許多小型查詢時。Django使用大型查詢來搶先在內存中創建模型,而不是針對數據庫執行按需查詢。
select_related對每個查找執行聯接,但將選擇范圍擴展為包括所有聯接表的列。但是,這種方法有一個警告。
聯接有可能使查詢中的行數相乘。當您通過外鍵或一對一字段執行聯接時,行數不會增加。但是,多對多聯接沒有此保證。因此,Django限制select_related了不會意外導致大規模聯接的關系。
對于“ join in python”來說prefetch_related,應該比它還要令人震驚。它為要連接的每個表創建一個單獨的查詢。它使用WHERE IN子句過濾每個表,例如:
SELECT "credential"."id",
"credential"."uuid",
"credential"."identity_id"
FROM "credential"
WHERE "credential"."identity_id" IN
(84706, 48746, 871441, 84713, 76492, 84621, 51472);
將每個表拆分為一個單獨的查詢,而不是執行可能包含太多行的單個聯接。

TA貢獻1820條經驗 獲得超9個贊
我會對您關于預取相關的評論“通常沒有多大意義”提出異議。對于標記為唯一的FK字段,這是正確的,但是在多行具有相同FK值(作者,用戶,類別,城市等)的任何地方,預取會減少Django和DB之間的帶寬,但不會重復行。通常,它在數據庫上使用的內存也較少。這些通常比單個額外查詢的開銷更為重要。鑒于這是一個相當普遍的問題的最佳答案,我認為應該在答案中注明。
添加回答
舉報