mysql - explain
explain + 查询语句,会返回mysql处理sql语句的分析结果
EXPLAIN SELECT t1.t_id FROM table1 t1 WHERE t1.t_id = (SELECT MIN(t_id) FROM table2) UNION SELECT t3.t_id FROM table3 t3
结果:
1.id: 表的读取顺序
代表优先级,数字越大,先被加载
2.select_type : 数据读取操作的操作类型
simple 简单查询,没有复杂结构
primary 有子查询时,最外层的是primary
subquery 子查询
derived 衍生的,一般会出现在from 后面跟select 时(嵌套查询)。
union union查询后面的table会被标记为union
union result union 查询的结果
3. table: 表名
4. type:访问类型
性能从好到差依次是:
1. system(系统类型:单行数据,const的特例,等于系统表,基本见不到) = =不过我测试的时候就算一条数据也达不到system。。。
2. const (常量类型:利用 主键,或者union index)
3. eq_ref (唯一索引 (union index) 扫描,只有一条记录匹配。)
4. ref (单行非唯一索引 (index) 扫描)
5. range (索引或者主键给定范围的查询 比如 select * from table1 where id > 1)
6. index (全索引扫描)
7. ALL (全表扫描)
正常情况下,尽量达到 ref 或者 range 级别已经可以满足大部分需求。
5. possible_keys
显示理论上可能应用在这次查询的索引(有可能possible_keys是null,而key有值,比如 select id from table1,查询的字段正好是索引,理论上不需要用到索引,但是mysql运行时用到了索引)
6. key
mysql实际查询时使用到的索引(null则为没有使用索引)
7. key_len
使用到的索引的最大长度(只是mysql推测,不是实际长度),越小越好。
一般条件越多,key_len越大 。
8. ref
索引被用来匹配了那些内容。cont是指常量 比如 id = 1 这种
如果有用到其他列则会显示匹配用到的列
9. rows
mysql估算的有多少行需要被扫描。(越小越好)
10. Extra
额外信息:
1. using filesort:使用了外部索引排序,mysql无法利用索引完成排序(说明在这次查询中包含了索引字段,但是索引没有被实际用到,最好优化一下)
2. using temporary: mysql完成查询时用到了临时表。
这两种最常见情况,是group by 后的字段顺序和内容跟复合索引不一致。
建一个表和索引用来测试:
CREATE TABLE index_test( t_id INT PRIMARY KEY, key1 INT, key2 INT, key3 INT, key4 INT ); INSERT INTO index_test VALUES(1,1,1,1,1); INSERT INTO index_test VALUES(2,1,2,3,4); INSERT INTO index_test VALUES(3,4,1,2,3); INSERT INTO index_test VALUES(4,3,4,1,2); INSERT INTO index_test VALUES(5,2,3,4,1); CREATE INDEX index_key1_key2_key3_key4 ON index_test(key1,key2,key3,key4);
原因:因为复合索引按照key1,key2,key3,key4的顺序进行了排序,直接用key3时,mysql虽然想用索引但是没有办法找到
比如 key1 = 4, key2 = 1, key3 = 2 在索引中在 key1 = 3, key2 = 4, key3 = 1 前面,mysql就无法利用索引快速定位 key3位置。
优化办法: 把索引顺序和字段能够对应上
3. using index: slq语句使用了覆盖索引,说明这次查询的结果是通过索引直接读取而不是查询到结果再读取结果所在行,效率很高。
比如key1,key2,key3,key4 是复合索引,我查key1,key2,key3,key4的值,mysql直接从这个索引表里读取key1,key2,key3,key4的数据, 而不是先定位 index_test 表中符合条件的列,然后从这个表中读取数据。
4. using where: 索引被用于查找(没有直接定位,而是在索引的基础上进行了查找)。
当查找的列不全是索引时,就不会有using index了
5. using join buffer: join太多,使用了缓存。
这时可以考虑 配置文件的join buffer调大一点。
6. impossible where: where错误,比如下面这种,key1 = 1 and key1 = 2,不可能
7.select tables optimized away: 没有group by时,mysql对count,min,max做了优化。 只是用来说明。
8. distinct: distinct时第一个结果就符合要求后不再寻找其他相同值。 只是用来说明。
extra主要作用: 针对1,2种情况,对sql语句进行优化。
11. filtered: 5.5 新加的列, rows扫描的结果中mysql估算有%多少被实际用到
当使用非索引作为查询条件时,遍历了5行,只发现了一个符合结果,只有20%的扫描结果被使用。所以这个值大一些比较好。