MySQL Explain
explain提供有关MySQL如何执行语句的信息,查看sql是怎样运行的,从而进行调优。MySQL官方文档
语法很简单,在sql语句之前加上explain就可以,如:EXPLAIN SELECT * FROM sys_user
查询结果如下:
输出列
列 | 解释 | json名称 |
---|---|---|
id | 查询语句标识 | select_id |
select_type | 查询的类型 | None |
table | 当前行所查的表 | table_name |
partitions | 匹配的分区 | partitions |
type | 访问的类型 | access_type |
possible_keys | 查询可能用的索引 | possible_keys |
key | 实际选择索引 | key |
key_len | 索引key的长度 | key_length |
ref | 与索引比较的列 | ref |
rows | 查询扫描的行数,预估值,不一定准确 | rows |
filtered | 按表条件过滤的行百分比 | filtered |
Extra | 附件信息 | None |
列的详解
- id: 查询顺序标识,sql由大到小执行。相同时从上往下执行。
- select_type: sql类型。如下:
(1)SIMPLE:SELECT查询
(2)PRIMARY:最外面的SELECT
(3)SUBQUERY :子查询SELECT
(4)DEPENDENT SUBQUERY : 子查询中的第一个SELECT,取决于外部查询
(5)DELETE:删除
(6)UPDATE:更新
(7)INSERT:增加
(8)UNION:UNION后面的SELECT
(9)UNION RESULT:UNION的结果
(10)DEPENDENT UNION: UNION中的第二个或更高的SELECT语句,取决于外部查询
(11)DERIVED:派生表——该临时表是从子查询派生出来的,位于from中的子查询
(12)UNCACHEABLE :SUBQUERY: 无法缓存结果的子查询,必须为外部查询的每一行重新计算
(13)UNCACHEABLE UNION: 在UNION中的第二个或更晚的选择属于不可缓存的子查询 - table:每一行引用的表名,真实表名或别名
- partitions:查询将匹配记录的分区。该值适用NULL于未分区的表
- type:从上到下效率依次降低
(0)null:没有查询表的时候才是null,比如:select ‘a’;
(1)system:const的一种特例,表中只有一行数据
(2)const:单表中最多只有一个匹配行(主键或者唯一索引)
(3)eq_ref:最多只返回一条符合条件的记录,通过使用在两个表有关联的字段的时候
(4)ref:指的是使用普通的索引(normal index)
(5)fultext:全文索引
(6)ref_or_null:跟ref相识,多一个不能为null的条件
(7)index_merge:此连接类型表示使用了索引合并优化。在这种情况下,输出行中的 key 列包含使用的索引列表,key_len包含所用索引的最长 key 部分列表
(8)unique_subquery:在使用 in 查询的情况下会取代 eq_ref
(9)range: 对索引进行范围扫描。key 列显示使用了哪个索引。当使用=、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN 操作符,用常量比较关键字列时,可以使用 range
(10)index:类似全表扫描,只是扫描表的时候按照索引次序进行而不是行。主要优点就是避免了排序, 但是开销仍然非常大。如在Extra列看到Using index,说明正在使用覆盖索引,只扫描索引的数据,它比按索引次序全表扫描的开销要小很多
(11)ALL:全表扫描
注:《阿里巴巴Java开发规范》推荐 SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,如果可以是consts最好
- possible_keys:MySQL可能采用的索引,但并不一定使用
- key:MySQL真正使用的索引名称
- key_len:索引的长度
- ref:列与索引的比较,表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
- rows:预估扫描的行数,只能参考,不准确
- filtered:查询的表行占表的百分比,值越大越好
- Extra:该列包含了很多额外的信息,包括是否文件排序,是否有临时表等,很多时候这个字段很有用能提供很多信息