在排查编写Mysql查询语句时,除了需要满足业务条件,还需要考虑所编写SQL的性能表现,避免出现慢SQL导致大量慢查询的情况。通常,可以通过查看执行计划的方式查看所编写SQL语句的性能优劣。此外,还可以通过查看语句的分阶段执行的时间、操作消耗来进行补充分析。
1. 执行计划的列
1.1. id列
查询的序号
1.2. select_type列
该列阐明查询的类型,有如下可能的取值(常见的):
值
释义
SIMPLE
简单查询,不涉及子查询或者UNION
PRIMARY
若包含UNION或者子查询,则最外层的查询标记为PRIMARY
UNION
UNION之后的的查询
DEPENDENT UNION
取决于外部查询的,UNION之后的查询
UNION RESULT
UNION的结果
SUBQUERY
在select中包含的子查询
DEPENDENT SUBQUERY
First SELECT in subquery, dependent on outer query
DERIVED
from中包含的子查询
…
1.3. table列
指定涉及到的表。
1.4. partitions列
仅在涉及分区表的情况下有,列出读取记录的分区
1.5. type列
Type列描述表的join方式(需要注意,mysql将任何一个查询都当做一个join,所以此处的join并不是内连接或者外连接)。其取值有如下几种,按照最优到最差排序:
1.5.1. system
表示该表仅有一行数据。这种情况是const的特殊情况。
1.5.2. const
该表仅有一行数据匹配,并且会在查询开始时就读取该条数据。因为仅有一行数据,该行数据的各列的值在后续查询优化时可以被当做常量。由于仅读取一次,const标识的表的查询非常快。
当全覆盖PRIMARY KEY 或者唯一索引作为查询条件做常量等值比较时,会采取const的join方式。
1.5.3. eq_ref
表示对于前一张表的每一行,当前表仅有一行与之匹配。eq_ref是除system与const之外最优的join方式。当索引为主键或者非空唯一索引,并且全部索引都使用到时,才会使用这种连接方式。
当在索引列使用’=’条件时,eq_ref可以作为连接方式。‘=’右边的条件可以为常量或者前表中的某一列。
1.5.4. ref
表示对前表的每一行,会读取当前表匹配索引的所有行。ref连接方式通常在条件满足最左前缀或者索引非主键和唯一索引的情况出现。当索引仅匹配出少数几行数据时,这种连接方式较优。
1.5.5. fulltext
通过全文索引(fulltext index)进行join
1.5.6. ref_or_null
与ref类型类似,与其不同的是会额外查询包含NULL值的行;在子查询解析中比较常见。
1.5.7. index_merge
表示使用了索引合并优化;索引合并是指,对于出现在条件中的列,如果在这些列上有索引或者满足最左前缀,通过多个索引获取结果集执行合并操作形成最终的结果集;索引合并不会跨表执行。
执行索引合并优化后,Extra列会列出合并操作的类型信息,包括:Using intersect/Using Union/Using sort_union几种。
1.5.8. unique_subquery/index_subquery
针对子查询作为IN条件的情况,若子查询的结果列满足(主键列、唯一索引列)/(普通索引),对子查询进行优化替换。
1.5.9. range
通过索引的方式选取并读取结果集。通常对于范围查询、BETWEEN、IN、IS NULL等满足。
1.5.10. index
除了通过扫描索引树获取数据,index与ALL类似。通常有两种形式:
1. 满足覆盖索引条件,即索引覆盖了查询所需的结果列,通过扫描索引树获取所需的结果;这种情况下Extra列显示Using index;这种情况比全表扫描更快,因为索引的大小通常小于表数据大小。
2. 通过扫描索引的方式执行全表扫描;这种情况下Extra列不会显示任何信息。
1.5.11. ALL
对于前表的每一行,执行全表扫描。全表扫描通常性能非常差,应该通过添加索引的方式避免。
1.6. possible_keys列
列出所有可能使用的索引
1.7. key列
Mysql决定使用的索引。可能出现key列列出的索引不在possible_keys当中的情况,通常是所需的结果列满足某个覆盖索引的情况。
1.8. key_len列
使用的索引的长度
1.9. ref列
显示利用索引进行数据筛选时的比较的列或者常量。常见的有const或者previos_table.some_index。
1.10. Extra列
Extra列显示Mysql解析查询的附加信息。在下篇文章中详细列出。