2011-07-21 33 views
6

我聽到很多人多年來說:使用「NOT EXISTS」被認爲是不好的SQL練習嗎?

「加入」運營商都優於「NOT EXISTS」

爲什麼?

+4

@duffymo:所有猜測都錯了。 – Quassnoi

+1

這是爲什麼關閉?我也很好奇原因。 –

+0

@Ziayo:可能是因爲「很多人」這個詞。如果措辭「比」不存在「更有效率,那麼這將是一個完美的問題,可以用」事實,參考或具體的專業知識「來解釋。 – Quassnoi

回答

9

MySQLOracleSQL ServerPostgreSQLNOT EXISTS是相同的效率或甚至比LEFT JOIN/IS NULL更有效。

雖然看起來「應該爲外部查詢中的每個記錄執行內部查詢」(這似乎對NOT EXISTS不利,對於NOT IN更糟糕,因爲後面的查詢甚至沒有關聯),它可能使用適當的anti-join方法進行優化,同時優化所有其他查詢。

SQL Server中,實際上,LEFT JOIN/IS NULL在內表中未指定索引或低基數列的情況下可能效率低於NOT EXISTS/NOT IN

人們經常聽說MySQL「在處理子查詢時尤其糟糕」。

這源於MySQL除了嵌套循環之外無法使用任何連接方法,這嚴重限制了它的優化能力。

當查詢將從此改寫子查詢的加入將是受益的唯一情況:

SELECT * 
FROM big_table 
WHERE big_table_column IN 
     (
     SELECT small_table_column 
     FROM small_table 
     ) 

small_table不會被查詢完全在big_table每個記錄:雖然似乎是相關不,它會通過查詢優化器,並在事實上改寫成EXISTS(使用index_subquery如果需要搜索第一多,如果small_table_column被索引)

big_table將永遠是領先的,這使得T爲含蓄地相關他在big * LOG(small)查詢完成而不是small * LOG(big)讀取。

這可以被改寫爲

SELECT DISTINCT bt.* 
FROM small_table st 
JOIN big_table bt 
ON  bt.big_table_column = st.small_table_column 

然而,這並不會提高NOT IN(相對於IN)。在MySQL,NOT EXISTSLEFT JOIN/IS NULL幾乎是相同的,因爲使用嵌套循環左表應該始終在LEFT JOIN領先。

您可能需要閱讀這些文章:

+0

這種情況多久了? –

+0

@伊恩:究竟是什麼? – Quassnoi

+0

@ Qnassnoi,效率大致相同 –

0

它可能與優化過程有關...不存在意味着子查詢,「優化器」通常不會執行子查詢正義。另一方面,加入可以更容易地處理...

0

我認爲這是一個MySQL的具體情況。 MySQL不優化IN /中的子查詢,而不是在/ any/not exists子句中,並且實際上爲外部查詢匹配的每一行執行子查詢。由於MySQL中的這一點,您應該使用連接。然而,在PostgreSQL中,你可以使用子查詢。

+1

它確實優化了所有這些子句。請閱讀http://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/ – Quassnoi

+0

@Darhazer,你似乎陷入MySQL版本4。 – Johan

+0

@Johan:......這也優化了所有這些構造。 – Quassnoi