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

Ian*_*ose 6 sql coding-style

多年来我听到很多人说:

"加入"运算符优先于"NOT EXISTS"

为什么?

Qua*_*noi 10

MySQL,Oracle,SQL ServerPostgreSQL,NOT 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
        )
Run Code Online (Sandbox Code Playgroud)

small_table对于每个记录都不会完全查询big_table:虽然它似乎没有相关性,但它会被查询优化器隐式关联,并且实际上被重写为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
Run Code Online (Sandbox Code Playgroud)

但是,这不会改善NOT IN(相反IN).在MySQL,NOT EXISTS并且LEFT JOIN / IS NULL几乎相同,因为对于嵌套循环,左表应始终在a中引导LEFT JOIN.

您可能想阅读这些文章:

  • @Ian:对于`Oracle` 和`SQL Server`,至少从我在这个行业开始(1997 年)。 (2认同)