共计 6025 个字符,预计需要花费 16 分钟才能阅读完成。
这篇文章主要介绍“分析 MySQL EXPLAIN 结果集”,在日常操作中,相信很多人在分析 MySQL EXPLAIN 结果集问题上存在疑惑,丸趣 TV 小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”分析 MySQL EXPLAIN 结果集”的疑惑有所帮助!接下来,请跟着丸趣 TV 小编一起来学习吧!
EXPLAIN:查看 SQL 语句的执行计划
EXPLAIN 命令可以帮助我们深入了解 MySQL 基于开销的优化器,还可以获得很多可能被优化器考虑到的访问策略的细节,以及当运行 SQL 语句时哪种策略预计会被优化器采用,在优化慢查询时非常有用
执行 explain 之后结果集包含如下信息
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------+
下面将对每一个值进行解释
1、id
id 用来标识整个查询中 SELELCT 语句的顺序,在嵌套查询中 id 越大的语句越先执行,该值可能为 NULL
id 如果相同,从上往下依次执行。id 不同,id 值越大,执行优先级越高,如果行引用其他行的并集结果,则该值可以为 NULL
2、select_type
select_type 表示查询使用的类型,有下面几种:
simple:
列类型长度备注 id int4+1int 为 4bytes, 允许为 NULL, 加 1byteid bigint not null8bigint 为 8bytesuser char(30) utf830*3+1utf8 每个字符为 3bytes, 允许为 NULL, 加 1byteuser varchar(30) not null utf830*3+2utf8 每个字符为 3bytes, 变长数据类型, 加 2bytesuser varchar(30) utf830*3+2+1utf8 每个字符为 3bytes, 允许为 NULL, 加 1byte, 变长数据类型, 加 2bytesdetail text(10) utf830*3+2+1TEXT 截取部分, 被视为动态列类型。
key_len 只指示了 where 中用于条件过滤时被选中的索引列,是不包含 order by 或 group by 这一部分被选中的索引列
8、ref
ref 列用来显示使用哪个列或常数与 key 一起从表中选择相应的行。它显示的列的名字(或 const),此列多数时候为 null
9、rows
rows 列显示的是 mysql 解析器认为执行此 SQL 时必须扫描的行数。此数值为一个预估值,不是具体值,通常比实际值小
10、filtered
此参数为 mysql 5.7 新加参数,指的是返回结果的行数所占需要读到的行(rows 的值)的比例
对于使用 join 时,前一个表的结果集大小直接影响了循环的行数
11、extra(重要)
extra 表示不在其他列并且也很重要的额外信息
using index: 该值表示这个 SQL 语句使用了覆盖索引(覆盖索引是指可以直接在索引列中得到想要的结果,而不用去回表),此时效率最高
mysql explain select id from test;
+----+-------------+-------+-------+---------------+----------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+----------+---------+------+-------+-------------+
| 1 | SIMPLE | test | index | NULL | idx_bnet | 9 | NULL | 68505 | Using index |
+----+-------------+-------+-------+---------------+----------+---------+------+-------+-------------+
这个例子中 id 字段为主键,但是 key 那里显示走的并不是主键索引,这个是因为 mysql 的所有二级索引中都会包含所有的主键信息,而 mysql 没有单独的存储主键索引,所以扫描二级索引的开销比全表扫描更快
using where: 表示存储引擎搜到记录后进行了后过滤(POST-FILTER),如果查询未能使用索引,using where 的作用只是提醒我们 mysql 要用 where 条件过滤结果集
mysql explain select * from test where id 1;
+----+-------------+-------+-------+---------------+---------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+-------+-------------+
| 1 | SIMPLE | test | range | PRIMARY | PRIMARY | 8 | NULL | 34252 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+-------+-------------+
using temporary 表示 mysql 需要使用临时表来存储结果集,常见于排序和分组查询
mysql explain select * from test where id in (1,2) group by bnet_id;
+----+-------------+-------+-------+-----------------------------------------+---------+---------+------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-----------------------------------------+---------+---------+------+------+----------------------------------------------+
| 1 | SIMPLE | test | range | PRIMARY,IDX(event_key-bnet_Id),idx_bnet | PRIMARY | 8 | NULL | 2 | Using where; Using temporary; Using filesort |
+----+-------------+-------+-------+-----------------------------------------+---------+---------+------+------+----------------------------------------------+
using filesort: 是指 mysql 无法利用索引直接完成排序(排序的字段不是索引字段),此时会用到缓冲空间来进行排序
mysql explain select * from test order by bnet_id;
+----+-------------+-------+------+---------------+------+---------+------+-------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------------+
| 1 | SIMPLE | test | ALL | NULL | NULL | NULL | NULL | 68505 | Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------------+
using join buffer: 强调在获取连接条件时没有用到索引,并且需要连接缓冲区来存储中间结果。(性能可以通过添加索引或者修改连接字段改进)
mysql explain select * from test left join test2 on test.create_time = test2.create_time;
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+----------------------------------------------------+
| 1 | SIMPLE | test | NULL | ALL | NULL | NULL | NULL | NULL | 959692 | 100.00 | NULL |
| 1 | SIMPLE | test2 | NULL | ALL | NULL | NULL | NULL | NULL | 958353 | 100.00 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+----------------------------------------------------+
2 rows in set, 1 warning (0.00 sec)
Block Nested Loop 是指 Block Nested-Loop Join 算法:将外层循环的行 / 结果集存入 join buffer, 内层循环的每一行与整个 buffer 中的记录做比较,从而减少内层循环的次数.
impossible where: 表示 where 条件导致没有返回的行
mysql explain select * from test where id is null;
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+
using index condition: 是 mysql 5.6 之后新加的特性,结合 mysql 的 ICP(Index Condition Pushdown)特性使用。主要是优化了可以在索引(仅限二级索引)上进行 like 查找
如果 extra 中出现多个上面结果,则表示顺序使用上面的方法进行解析查询
到此,关于“分析 MySQL EXPLAIN 结果集”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注丸趣 TV 网站,丸趣 TV 小编会继续努力为大家带来更多实用的文章!