【问题标题】:Why does a query with an IN (subquery) take longer than a query with IN (discrete list)为什么带有 IN(子查询)的查询比带有 IN(离散列表)的查询花费更长的时间
【发布时间】:2015-04-25 01:00:17
【问题描述】:

这个问题一直困扰着我,为什么会这样查询

SELECT 
  * 
FROM
  `TABLE` 
WHERE `value` IN 
  (SELECT 
    val 
  FROM
    OTHER_TABLE 
  WHERE `date` < '2014-01-01')

运行速度比顺序运行这两个查询慢几个数量级

SELECT 
  `val` 
FROM
  OTHER_TABLE 
WHERE `date` < '2014-01-01' 

Result:
+----+
| val |
+-----+
| v1  |
| v2  |
| v3  |
| v7  |
| v12 |
+-----+

这个查询:

SELECT 
  * 
FROM
  `TABLE` 
WHERE `value` IN ('v1', 'v2', 'v3', 'v7', 'v12')

【问题讨论】:

    标签: mysql subquery correlated-subquery


    【解决方案1】:

    来自文档:(重点由我添加)

    IN 的子查询优化不如 = 运算符有效 或IN(value_list) 运算符。

    IN 子查询性能不佳的典型情况是当子查询 返回少量行,但外部查询返回大 要与子查询结果进行比较的行数。

    问题在于,对于使用IN 子查询的语句, 优化器将其重写为相关子查询。考虑以下 使用不相关子查询的语句:

    SELECT ... FROM t1 WHERE t1.a IN (SELECT b FROM t2);

    优化器将语句重写为相关子查询:

    SELECT ... FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.b = t1.a);

    如果内部和外部查询分别返回 M 和 N 行,则 执行时间变为O(M×N),而不是O(M+N) 这将是一个不相关的子查询。

    暗示IN 子查询可能比查询慢得多 使用列出相同值的IN(value_list) 运算符编写 子查询将返回。

    http://dev.mysql.com/doc/refman/5.7/en/subquery-restrictions.html

    希望这可以帮助其他可能好奇的人

    【讨论】:

    • 所有版本都是这样吗?
    • @Strawberry 好问题,我在谷歌上找到了这个答案(在寻找其他东西时),并且 5.0 文档碰巧出现了。我已验证文章的 该部分 与 5.7 文档相同,并且我已相应更新链接
    • @Strawberry:这种说法已经有很长时间了;我不能说它适用于所有版本。 (在 MySQL 3.23 中,我们甚至不能使用子查询。)这种有据可查的行为和经过良好测试的性能差异是我们中的一些人不断并强烈主张替代无处不在的IN/NOT IN (subquery) 形式。对于小型设备来说,这从来都不是问题,我们从未注意到性能差异。只有当我们扩展到真实数据量时,性能差异才会显着
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多