多年来我听到很多人都说:
“加入”运算符优先于“NOT EXISTS”
为什么?
答案 0 :(得分:10)
在MySQL
,Oracle
,SQL Server
和PostgreSQL
中,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
中,MySQL
和NOT EXISTS
几乎相同,因为对于嵌套循环,左表应始终位于LEFT JOIN / IS NULL
中。
您可能想阅读这些文章:
答案 1 :(得分:0)
它可能与优化过程有关... NOT EXISTS意味着子查询,而“优化器”通常不会使子查询正义。另一方面,联接可以更容易处理......
答案 2 :(得分:0)
我认为这是MySQL特有的情况。 MySQL不优化IN / not in / any / not exists子句中的子查询,并且实际上为外部查询匹配的每一行执行子查询。因为在MySQL中,你应该使用join。但是在PostgreSQL中,你可以使用子查询。