Mysql存在vs IN相关子查询vs子查询?

我很好奇,EXISTS()的执行应该比IN()更快.

比尔·卡尔温提出了一个好点,我是answering a question.当您使用EXISTS()时,它正在使用相关的子查询(依赖子查询),IN()仅使用子查询.

EXPLAIN显示EXISTS和NOT EXISTS都使用依赖子查询和IN / NOT IN都只使用一个子查询..所以我很好奇相关子查询比子查询更快?

我以前使用EXISTS,它比IN更快地执行,这就是为什么我感到困惑.

这是一个SQLFIDDLE与解释

EXPLAIN SELECT COUNT(t1.table1_id) 
FROM table1 t1 
WHERE EXISTS
(   SELECT 1 
    FROM table2 t2
    WHERE t2.table1_id <=> t1.table1_id
);

+-------+-----------------------+-----------+-------+---------------+-----------+--------+--------------------------+--------+------------------------------+
| ID    |   SELECT_TYPE         |   TABLE   | TYPE  | POSSIBLE_KEYS |   KEY     |KEY_LEN |  REF                     |   ROWS |  EXTRA                       |
+-------+-----------------------+-----------+-------+---------------+-----------+--------+--------------------------+--------+------------------------------+
|  1    |   PRIMARY             |   t1      | index | (null)        |   PRIMARY |   4    | (null)                   |   4    |  Using where; Using index    |
|  2    |   DEPENDENT SUBQUERY  |   t2      | REF   | table1_id     |  table1_id|   4    | db_9_15987.t1.table1_id  |   1    |  Using where; Using index    |
+-------+-----------------------+-----------+-------+---------------+-----------+--------+--------------------------+--------+------------------------------+
EXPLAIN SELECT COUNT(t1.table1_id) 
FROM table1 t1 
WHERE NOT EXISTS
(   SELECT 1 
    FROM table2 t2
    WHERE t2.table1_id = t1.table1_id
);
+-------+-----------------------+-----------+-------+---------------+-----------+--------+--------------------------+--------+------------------------------+
| ID    |   SELECT_TYPE         |   TABLE   | TYPE  | POSSIBLE_KEYS |   KEY     |KEY_LEN |  REF                     |   ROWS |  EXTRA                       |
+-------+-----------------------+-----------+-------+---------------+-----------+--------+--------------------------+--------+------------------------------+
|  1    |   PRIMARY             |   t1      | index | (null)        |   PRIMARY |   4    | (null)                   |   4    |  Using where; Using index    |
|  2    |   DEPENDENT SUBQUERY  |   t2      | ref   | table1_id     |  table1_id|   4    | db_9_15987.t1.table1_id  |   1    |  Using index                 |
+-------+-----------------------+-----------+-------+---------------+-----------+--------+--------------------------+--------+------------------------------+
EXPLAIN SELECT COUNT(t1.table1_id) 
FROM table1 t1 
WHERE t1.table1_id NOT IN 
(   SELECT t2.table1_id 
    FROM table2 t2
);
+-------+-------------------+-----------+-------+---------------+-----------+--------+----------+--------+------------------------------+
| ID    |   SELECT_TYPE     |   TABLE   | TYPE  | POSSIBLE_KEYS |   KEY     |KEY_LEN |  REF     |   ROWS |  EXTRA                       |
+-------+-------------------+-----------+-------+---------------+-----------+--------+----------+--------+------------------------------+
|  1    |   PRIMARY         |   t1      | index | (null)        |   PRIMARY |   4    | (null)   |   4    |  Using where; Using index    |
|  2    |   SUBQUERY        |   t2      | index | (null)        |  table1_id|   4    | (null)   |   2    |  Using index                 |
+-------+-------------------+-----------+-------+---------------+-----------+--------+----------+--------+------------------------------+

几个问题

在上面的解释中,EXISTS如何使用在附加组件中使用索引的位置,而不是使用除了EXISTS之外的索引?

相关子查询如何比子查询更快?

最佳答案
这是一个与RDBMS无关的答案,但可能有帮助.在我的理解中,相关(又一个,依赖的)子查询也许是错误的被指责的罪魁祸首.

问题(最常被描述)是它处理外部查询的每一行的内部查询.因此,如果外部查询返回1000行,并且内部查询返回10,000,则查询必须通过10,000,000行(外部×内部)来排序以产生结果.与11,000行(外部内部)相比,在相关结果集中的非相关查询中,这不是很好.

但是,这只是最糟糕的情况.在许多情况下,DBMS将能够利用索引来大大减少rowcount.即使只有内部查询可以使用索引,10,000行将变为〜13寻找,总共下降到13,000.

存在的运算符可以在第一行后停止处理行,进一步减少查询成本,特别是当大多数外部行与至少一个内部行匹配时.

在一些罕见的情况下,我已经看到SQL Server 2008R2将关联子查询优化到合并连接(其仅遍历两个集合一次 – 最佳可能的情况),其中可以在内部和外部查询中找到合适的索引.

性能不佳的真正原因不一定是相关的子查询,而是嵌套扫描.

转载注明原文:Mysql存在vs IN相关子查询vs子查询? - 代码日志