explain字段可以分优先顺序看,但是要结合着看。
一、字段
【type】:查询计划对某个表的查询方式,表示关联类型或访问类型,即MySQL决定如何查找表中的行,查找数据行记录的大概范围
依次从最优到最差分别为:system > const > eq_ref > ref > range > index > ALL
一般来说,得保证查询达到range级别,最好达到ref。
NULL:
system: 表数据只存在一条出现该属性值;表中只有一条数据,这个类型是特殊的 const 类型。
const: 查询条件只使用唯一索引(索引列值是唯一的),且最终结果只有一条记录(索引只扫描一次);(比较理想的状态)
表连接情况下,使用连接字段为唯一索引,且最终连接结果只有一条结果匹配(索引只扫描一次);
eq_ref:与const一样,只使用唯一索引,但是匹配结果是多条;
ref:查询条件或者连接条件出现非唯一索引;(比较经常看到的是这个)
range:查询条件索引字段出现范围查询,如in,or等;这个类型通常出现在 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN() 操作中。
index:使用到了索引,即为index;type=index 执行效率仅高于全表扫描,是扫描了全部索引后才完成的操作,在某些情况下比全部扫描更差。key_len比较大,说明索引太长。
All:没有索引或全表扫描。全表扫描,MYSQL扫描全表来找到匹配的行。
【possible_keys】:查询时可能使用到哪些索引。
explain 时可能出现 possible_keys 有列,而 key 显示 NULL 的情况,这种情况是因为表中数据不多,mysql认为索引对此查询帮助不大,选择了全表查询。
【key】:实际上使用到的索引。
【key_len】:显示了mysql在索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列。
这一列显示mysql实际采用哪个索引来优化对该表的访问。如果没有使用索引,则该列是 NULL。如果想强制mysql使用或忽视possible_keys列中的索引,在查询中使用 force index、ignore index。
【ref】:在key列记录的索引中,表查找值所用到的列或常量,常见的有:const(常量),字段名。
【rows】:扫描出的行数(很有参考意义),这个是个估算的值,并不是真正的结果集。(mysql估计要读取并检测的行数,注意这个不是结果集里的行数。)
【Extra】:展示的是额外信息。Extra,主要看使用 order by 进行排序时有没有出现 Using filesort 和 Using index。
尽量通过 order by 和 where 配合,可以出现 Using index。避免 Using filesort。
那么什么时候会出现 Using index 呢?order by 语句满足索引最左前缀,where 和 order by 条件列组合满足索引最左前缀。
Using index:表示使用了覆盖索引,速度比较快。
Using where:使用 where 语句来处理结果,并且查询的列未被索引覆盖。(这种情况一般需要优化了)。
Using index condition:查询的列不完全被索引覆盖,where条件中是一个前导列的范围。
Using temporary:mysql需要创建一张临时表来处理查询。(出现这种情况一般是要进行优化的),首先是想到用索引来优化。
Using filesort:将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序。(这种情况下一般也是要考虑使用索引来优化的。)
Select tables optimized away:使用某些聚合函数(比如 max、min)来访问存在索引的某个字段。
二
二、小记
1、不同的表数据对同一个sql可能explain的结果会不一样,因为在不强制的情况下MySQL一般都有自己的想法选择索引;
2、通常情况下 等值匹配的索引命中理论上只要符合 左侧原则等即可,如过非等值匹配则另说。特别是 带有order by 条件的语句需要视情况配合where设置为组合索引才能生效。
如:select * from tbname where A=1 and B!=2 and addTime<'20100305' order by addTime desc limit 1;
虽然此时很可能type=ref,但是Extra是Using where;Using filesort等。此时并不代表索引OK。
若此时索引为 A,addTime。则Using where还可能Using filesort。要特别注意,带 order by的语句如果不是和where 组合索引而是各自字段索引很可能就是Using filesort,需要优化。通常我们会误以为 对where和order by 的各自字段单独建立索引就可以命中的。
若此时索引为 (A,addTime)。则Using where。此时应该关注 A字段索引是否是可以查一条,即rows=1。当A基本为相同值时,例如日期,但是同一日期的数据有可能几十万条时,则说明rows约等于几十万,也就是要扫描这么多数据,则索引索引命中但基本不发挥作用,应优化。
鉴于A字段建立的索引基本是相同值,所以考虑将A索引弃用。考虑调整为where B!=2 and addTime<'20100305' order by addTime desc limit 1; 若此时索引为addTime字段。一般情况下,此时会用上索引 addTime但是有可能因为 addTime<'20100305' 条件又要扫描上千万条数据中去找 降序的最上面一条。也不合理。
最终,where B!=2 order by addTime desc limit 1; 且若此时索引为addTime字段,则命中索引addTime且rows=1,这样才行。才不会慢查询。
其他参考资料:
网友评论