MySQL - NOT IN ... 与 LEFT JOIN

omr*_*mri 5 mysql innodb

我试图从性能方面了解哪种方法更好:

查询1:

SELECT * FROM table1
WHERE col1 NOT IN(SELECT col1 FROM table2)
Run Code Online (Sandbox Code Playgroud)

查询2:

SELECT * FROM table1
LEFT JOIN table2 ON table1.col1 = table2.col1
WHERE table2.col1 IS NULL
Run Code Online (Sandbox Code Playgroud)

第一个查询使用DEPENDENT SUBQUERY,第二个查询仅使用索引。

jka*_*lik 5

EXPLAIN告诉你其中的区别。

如果它显示DEPENDENT SUBQUERY,则意味着子查询 inIN()每行执行一次table1,如果表很大,则可能会执行很多次。

不同的 MySQL 版本可能会对第一个查询应用不同的优化,以消除DEPENDENT SUBQUERY或至少最小化其性能影响:

  • col1使用子查询缓存 - 如果值中有很多重复项可能会很好
  • 变成NOT INNOT EXISTS
  • 将子查询具体化为临时表并(左)连接到它
  • 将查询重写为直接左连接

如果您的优化器没有应用这些,请使用第二个查询,因为 MySQL 可以更好地优化连接(在旧版本中更是如此)。在大多数情况下,制定计划DEPENDENT SUBQUERY并不有效。

IIRC可以通过对该计划的具体优化LEFT JOIN ... IS NULL进行评估。NOT EXISTS

对于这两个查询,您应该有一个索引,table2.col1以允许快速执行子查询或快速检测该行是否存在(不存在)。