3 回答

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

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