使用“NOT EXISTS”被认为是错误的SQL实践吗?

时间:2011-07-21 14:05:37

标签: sql coding-style

多年来我听到很多人都说:

  

“加入”运算符优先于“NOT EXISTS”

为什么?

3 个答案:

答案 0 :(得分:10)

MySQLOracleSQL ServerPostgreSQL中,NOT EXISTS效率相同,效率甚至高于LEFT JOIN / IS NULL。< / p>

虽然看起来“应该对来自外部查询的每条记录执行内部查询”(这似乎对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:虽然它似乎没有相关性,但它会被查询优化器隐式关联,实际上会被重写为{{1} (如果EXISTS被编入索引,则使用index_subquery搜索第一个,如果需要的话)

small_table_column始终处于领先地位,这使得查询在big_table完成,而不是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中,MySQLNOT EXISTS几乎相同,因为对于嵌套循环,左表应始终位于LEFT JOIN / IS NULL中。

您可能想阅读这些文章:

答案 1 :(得分:0)

它可能与优化过程有关... NOT EXISTS意味着子查询,而“优化器”通常不会使子查询正义。另一方面,联接可以更容易处理......

答案 2 :(得分:0)

我认为这是MySQL特有的情况。 MySQL不优化IN / not in / any / not exists子句中的子查询,并且实际上为外部查询匹配的每一行执行子查询。因为在MySQL中,你应该使用join。但是在PostgreSQL中,你可以使用子查询。