【问题标题】:Why doesn't mysql optimize this simple query为什么mysql不优化这个简单的查询
【发布时间】:2015-05-08 00:44:55
【问题描述】:

假设列 pkey 是 mysql 表 T 的主键。基于 EXPLAIN 输出:

  1. 对于 DERIVED 和 PRIMARY 选择,此查询只需要扫描 1 行(正如人们所期望的那样):

    SELECT * FROM (SELECT * FROM T where pkey=10) t;

  2. 但是这个查询需要对两个 DERIVED 和 PRIMARY select 做一个完整的线性扫描(这表明 MySQL 根本无法优化查询):

    SELECT * FROM (SELECT * FROM T) t where pkey=10;

查询 #2 至少有两种可能的优化:可以将其转换为 #1,或者完全删除子查询(即将其更改为 SELECT * FROM T where pkey=10),以及可能的其他优化。

MySQL 无法优化查询是否有更深层次的原因,即优化是否有可能会改变查询的可观察行为(在这种情况下,MySQL 通过不优化来做正确的事情)?

PS:我正在运行 MySQL 版本 5.6.13。

【问题讨论】:

  • 一般情况下,外表不是内表,也没有内表的索引。我对 MySQL 开发人员没有洞察力,但如果它是如此微不足道,甚至人类也可以做到,那么人类可能有理由不这样做,也不应该碰它。 DBMS 优化是关于如何尽可能快地执行查询,而不是关于如何将错误的查询重写为更好的查询。
  • MySQL 不会将外部查询中的谓词下推到视图查询中。为什么? MySQL 优化器中没有执行该操作的代码路径。它不会发生,因为没有代码可以做到这一点。正如 Gordon 的回答很好地解释的那样,MySQL 对该语句的作用正是 MySQL 对它的作用。 (这种行为的一个好处是我们可以从 MySQL 优化器中获得非常可预测的执行计划。)
  • @Amadan:问题是关于 为什么 它不优化它,而不是为什么在第二种情况下需要两次线性扫描(这很明显,一旦你知道它不会优化它)。请参阅下面戈登的回答。而且你用你的轻率陈述否定了整个优化领域“如果它是如此微不足道以至于人类可以做到,也许人类有理由不这样做”。除非您可以根据 mysql 规范(就任何可观察的效果而言)判断这两个查询有何不同,否则您不能排除优化的可能性。
  • 我相信我在第一句话中陈述了 Gordon 所做的几乎相同的事情,以及 spencer7583 关于 MySQL 优化的可预测性所做的相同事情。我宁愿说你应该感谢@spencer7583,因为他给了你更多的技术解释。
  • 如果你看你上面的评论,我看到了。

标签: mysql sql database query-optimization


【解决方案1】:

MySQL 实现子查询。因此,当您编写此代码时(固定为子查询有别名):

SELECT *
FROM (SELECT * FROM T) t
WHERE pkey = 10;

您告诉 SQL 引擎将 T 复制到中间临时表中。这个表没有索引,所以这个查询比第一个版本要贵很多。

这是 MySQL 的一个特性。几乎任何其他数据库都可以正确处理这个问题。我认为即使是 MS Access 也是如此。

【讨论】:

  • 在 MySQL venacular 中,该内联视图(别名为t)被称为派生表。当我们了解 MySQL 如何处理它时,他们使用的名称是有道理的。内联视图查询的结果物化为一个表。一旦该步骤完成,外部查询就可以针对新填充的表运行。 (我们在存储视图中也观察到了同样的行为。)并且 MySQL 确实将谓词从外部查询下推到视图查询中,就像大多数其他 RDBMS 所做的那样。
猜你喜欢
  • 2012-03-20
  • 2012-06-13
  • 2013-12-18
  • 1970-01-01
  • 2021-12-04
  • 1970-01-01
  • 2012-04-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多