2015-05-08 58 views
-2

假设列pkey是mysql表T的主键。基于解释输出:为什么mysql不优化这个简单的查询

  1. 此查询需要扫描每个只有1行两种推导PRIMARY选择(正如人们所期望的那样):

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

  2. 但此查询需要为执行完整的线性扫描 DERIVED和PRIMARY选择(这表示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。

+1

外表不是一般情况下的内表,也不具有内表的索引。我对MySQL开发人员没有深入的了解,但如果它太微不足道了,即使是人类也可以这么做,也许人类有理由不这样做,也不应该触及它。 DBMS优化是关于如何执行尽可能快的查询,而不是如何将错误查询重写为更好的查询。 – Amadan

+0

MySQL不会将外部查询的谓词向下推入视图查询中。为什么? MySQL优化器中没有执行该操作的代码路径。它不会发生,因为没有代码可以做到这一点。正如Gordon的答案很好地解释的,MySQL对该陈述所做的是MySQL正是如此。 (这种行为的好处之一就是我们从MySQL优化器中获得了非常可预测的执行计划。) – spencer7593

+1

@Amadan: 问题是关于*为什么*它没有优化它,而不是为什么两个线性第二种情况下需要扫描(这很明显,一旦知道它不会优化它)。请参阅Gordon的答案。 而你正在用你轻浮的陈述来打击整个优化领域:“如果它太微不足道了,人类可以做到,也许人类有理由不这样做”。除非你可以告诉每个mysql规格的两个查询是如何不同的(就任何可观察到的效果而言),否则你不能排除优化的可能性。 – abi

回答

3

MySQL实现了子查询。所以,当你写这个(固定有子查询的别名):

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

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

这是MySQL的一个特点。几乎任何其他数据库都能正确处理。我认为即使MS Access的。

+1

在MySQL中,*内联视图*(别名为't')被称为**派生表**。当我们理解MySQL如何处理这个名称时,他们使用的名称是有道理的。内联视图查询的结果是* materialized *作为表。完成该步骤后,外部查询可以针对新填充的表运行。 (我们也观察到存储视图的相同行为。)和其他大多数RDBMS一样,MySQL不会将外部查询中的谓词向下推入视图查询中。 – spencer7593