mysql的explain
语句能查看sql的执行计划,根据执行计划能分析写的sql的执行效率.是优化sql的常用工具之一.
模拟数据
首先模拟订单数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
drop table if exists tbl_order_info;
CREATE TABLE `tbl_order_info` (
`id` int(11) NOT NULL auto_increment,
`amount` decimal(12,2) DEFAULT NULL,
`user_no` varchar(32) DEFAULT NULL,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录更新时间',
PRIMARY KEY (`id`),
KEY `idx_user_no` (`user_no`),
KEY `idx_amount` (`amount`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
drop procedure if exists insert_tbl_order_info;
delimiter ;;
create procedure insert_tbl_order_info()
begin
declare i int;
set i=1;
while(i<=1000)do
insert into tbl_order_info(amount, user_no) values(i, i+1);
set i=i+1;
end while;
end;;
delimiter ;
call insert_tbl_order_info();
|
执行explain
查询user_no
为999的订单信息.查看此sql的执行计划.
1
2
|
explain select * from tbl_order_info
where user_no='999';
|
输出:
1
2
3
4
5
6
|
+----+-------------+----------------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | tbl_order_info | NULL | ref | idx_user_no | idx_user_no | 131 | const | 1 | 100.00 | NULL |
+----+-------------+----------------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
|
执行计划显示,select_type:是简单查询,key:查询使用idx_user_no索引,type:基于普通索引的等值查询,ref:和索引比较的是常量.
explain输出字段含义
列名 |
解释 |
id |
查询编号 |
select_type |
查询类型:显示本行是简单还是复杂查询 |
table |
涉及到的表 |
partitions |
匹配的分区:查询将匹配记录所在的分区.仅当使用 partition 关键字时才显示该列。对于非分区表,该值为 NULL。 |
type |
本次查询的表连接类型 |
possible_keys |
可能选择的索引 |
key |
实际选择的索引 |
key_len |
被选择的索引长度:一般用于判断联合索引有多少列被选择了 |
ref |
与索引比较的列 |
filtered |
按条件筛选的行的百分比 |
Extra |
附加信息 |
explain中select_type
select的值 |
解释 |
SIMPLE |
简单查询 (不使用关联查询或子查询) |
PRIMARY |
如果包含关联查询或者子查询,则最外层的查询部分标记为 primary |
UNION |
联合查询中第二个及后面的查询 |
DEPENDENT UNION |
满足依赖外部的关联查询中第二个及以后的查询 |
UNION RESULT |
联合查询的结果 |
SUBQUERY |
子查询中的第一个查询 |
DEPENDENT SUBQUERY |
子查询中的第一个查询,并且依赖外部查询 |
DERIVED |
用到派生表的查询 |
MATERIALIZED |
被物化的子查询 |
UNCACHEABLE SUBQUERY |
一个子查询的结果不能被缓存,必须重新评估外层查询的每一行 |
UNCACHEABLE UNION |
关联查询第二个或后面的语句属于不可缓存的子查询 |
explain中type
type的值 |
解释 |
system |
查询对象表只有一行数据,且只能用于 MyISAM 和 Memory 引擎的表,这是最好的情况 |
const |
基于主键或唯一索引查询,最多返回一条结果 |
eq_ref |
表连接时基于主键或非 NULL 的唯一索引完成扫描 |
ref |
基于普通索引的等值查询,或者表间等值连接 |
fulltext |
全文检索 |
ref_or_null |
表连接类型是 ref,但进行扫描的索引列中可能包含 NULL 值 |
index_merge |
利用多个索引 |
unique_subquery |
子查询中使用唯一索引 |
index_subquery |
子查询中使用普通索引 |
range |
利用索引进行范围查询 |
index |
全索引扫描 |
ALL |
全表扫描 |
上表的这些情况,查询性能从上到下依次是最好到最差. |
|
Extra常见的值 |
解释 |
Using filesort |
将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序 |
Using temporary |
需要创建一个临时表来存储结构,通常发生对没有索引的列进行 GROUP BY 时 |
Using index |
使用覆盖索引 |
Using where |
使用 where 语句来处理结果 |
Impossible WHERE |
对 where 子句判断的结果总是 false 而不能选择任何数据 |
Using join buffer (Block Nested Loop) |
关联查询中,被驱动表的关联字段没索引 |
Using index condition |
先条件过滤索引,再查数据 |
Select tables optimized away |
使用某些聚合函数(比如 max、min)来访问存在索引的某个字段 |
sql分析的其他方式
show profile
,trace
等工具也能分析我们的sql.explain
是查看执行计划,show profile
是查看sql执行过程中各部分的耗时.
trace
是查看sql执行过程中的详细信息,使用了哪些索引,为什么使用,为何选取什么样子的排序方式等.