2011-07-21 34 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