EXPLAIN是MySQl必不可少的一个分析工具,主要用来测试sql语句的性能及对sql语句的优化,或者说模拟优化器执行SQL语句。
在select语句之前增加explain关键字,执行后MySQL就会返回执行计划的信息,而不是执行sql。但如果from中包含子查询,MySQL仍会执行该子查询,并把子查询的结果放入临时表中。它显示了mysql如何使用索引来处理select语句以及连接表,可以帮助选择更好的索引和写出更优化的查询语句。
explain可用来分析SQL的执行计划。格式如下:
{EXPLAIN
DESCRIBE
DESC}
tbl_name[col_name
wild]
[explain_type]
{explainable_stmt
FORCONNECTIONconnection_id}
{EXPLAIN
DESCRIBE
DESC}ANALYZEselect_statement
explain_type:{
FORMAT=format_name
}
format_name:{
TRADITIONAL
JSON
TREE
explainable_stmt:{
SELECTstatement
TABLEstatement
DELETEstatement
INSERTstatement
REPLACEstatement
UPDATEstatement
结果解读:
id
该语句的唯一标识。如果explain的结果包括多个id值,则数字越大越先执行;而对于相同id的行,则表示从上往下依次执行。
select_type
查询类型,有如下几种取值:
查询类型作用
table
表示当前这一行正在访问哪张表,如果SQL定义了别名,则展示表的别名
partitions
当前查询匹配记录的分区。对于未分区的表,返回null
type
连接类型,有如下几种取值,性能从好到坏排序如下:
1system:该表只有一行(相当于系统表),system是const类型的特例
2const:针对主键或唯一索引的等值查询扫描,最多只返回一行数据.const查询速度非常快,因为它仅仅读取一次即可
3eq_ref:当使用了索引的全部组成部分,并且索引是PRIMARYKEY或UNIQUENOTNULL才会使用该类型,性能仅次于system及const。
--多表关联查询,单行匹配
SELECT*FROMref_table,other_table
WHEREref_table.key_column=other_table.column;
--多表关联查询,联合索引,多行匹配
WHEREref_table.key_column_part1=other_table.column
ANDref_table.key_column_part2=1;
4ref:当满足索引的最左前缀规则,或者索引不是主键也不是唯一索引时才会发生。如果使用的索引只会匹配到少量的行,性能也是不错的。
--根据索引(非主键,非唯一索引),匹配到多行
SELECT*FROMref_tableWHEREkey_column=expr;
--多表关联查询,单个索引,多行匹配
TIPS
最左前缀原则,指的是索引按照最左优先的方式匹配索引。比如创建了一个组合索引(column1,column2,column3),那么,如果查询条件是:
WHEREcolumn1=1、WHEREcolumn1=1ANDcolumn2=2、WHEREcolumn1=1ANDcolumn2=2ANDcolumn3=3都可以使用该索引;WHEREcolumn1=2、WHEREcolumn1=1ANDcolumn3=3就无法匹配该索引。
5fulltext:全文索引
6ref_or_null:该类型类似于ref,但是MySQL会额外搜索哪些行包含了NULL。这种类型常见于解析子查询
SELECT*FROMref_table
WHEREkey_column=exprORkey_columnISNULL;
7index_merge:此类型表示使用了索引合并优化,表示一个查询里面用到了多个索引
8unique_subquery:该类型和eq_ref类似,但是使用了IN查询,且子查询是主键或者唯一索引。例如:
valueIN(SELECTprimary_keyFROMsingle_tableWHEREsome_expr)
9index_subquery:和unique_subquery类似,只是子查询使用的是非唯一索引
valueIN(SELECTkey_columnFROMsingle_tableWHEREsome_expr)
10range:范围扫描,表示检索了指定范围的行,主要用于有限制的索引扫描。比较常见的范围扫描是带有BETWEEN子句或WHERE子句里有、=、、=、ISNULL、=、BETWEEN、LIKE、IN()等操作符。
SELECT*FROMtbl_name
WHEREkey_columnBETWEEN10and20;
WHEREkey_columnIN(10,20,30);
11index:全索引扫描,和ALL类似,只不过index是全盘扫描了索引的数据。