MySQL Explain之“Select tables optimized away”
MySQL Explain之“Select tables optimized away”
今天使用MySQL的时候突发奇想的对select max(id) from t1
这种语句用了下explain,在结果里面的Extra里面显示Select tables optimized away
。下面的内容摘自MySQL官方文档。
优化器会确定两件事:第一个是至多返回一行;第二个是为了返回第一行,必须读取可确定的一些行。这些行会在优化期间被读取(例如,读取索引),查询期间不需要读取任何表。
第一个条件在查询中有隐式分组的被满足(有聚合函数但是没有GROUP BY子句)。第二个条件在使用索引进行查找的时候满足。读取的索引的数量决定了需要读取的行数。
考虑下面这个隐式分组查询:
SELECT MIN(c1), MIN(c2) FROM t1;
假设MIN(c1)可以通过读取一个索引获得,MIN(c2)可以通过读取另一个索引获得。换句话说,对于列c1,c2都存在一个索引,并且这两个索引的第一列是c1和c2。在这种情况下,读取两个确定的行可返回一个结果。
如果读取的行不确定,那么Extra列不会出现该提示,考虑下面的行:
SELECT MIN(c2) FROM t1 WHERE c1 <= 10;
假设(c1,c2)是覆盖索引,使用这个索引,所有c1 <= 10的行必须被扫描来查找最小的c2。相比之下,看下面的查询:
SELECT MIN(c2) FROM t1 WHERE c1 = 10;
在这种情况下,索引的第一列c1 = 10的列中包含了最小的c2列。只有一行必须被读取来获取返回的行。
对于MyISAM表,每个表里面里面有一个额外的行包含了表中的行数,当执行没有WHERE子句,或者WHERE子句恒定为true,并且没有GROUP BY的COUNT(*)查询的时候,Extra也会出现(这是隐式分组查询的一个实例,存储引擎会影响是否读取确定的行)。
总结,Explain出现这个提示是说明这个查询直接通过扫描索引就能得到。
除了上面例子中的sql,下面这个也可以,c1是索引:
SELECT MIN(c1) FROM t1 WHERE c1 < 30;
还有上面提到的,如果是多列索引(c1,c2),下面第一个sql是可以的,但是聚合函数参数是c2是不行的,这与索引的使用原理是一样的:
SELECT MIN(c1) FROM t1;
-- 这两个是不行的
SELECT MIN(c2) FROM t1;
SELECT MIN(c1), MIN(c2) FROM t1;
(完)
- 本文作者:吴泽辉
- 本文链接:https://mutex.top/posts/ccafcdd1/
- 发表日期:2018年6月14日
- 版权声明:本文章为原创,采用《知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议》进行许可