今天让我们了解下 MySQL 性能分析大杀器 —— explain
使用 explain 可以模拟优化器执行 SQL 查询语句,从而知道 MySQL 怎么处理你的 SQL 语句的,分析你的查询语句和表结构的性能瓶颈。
如何使用 explain
使用方式,直接在 sql 语句前加上 explain 即可。例如,如下:
explain select * from users;
-- 本意为显示警告信息。但是和 explain 一块儿使用,就会显示出优化后的 sql。需要注意使用顺序。(两条 sql 需要放在一起同时执行,因此 explain 后面一定要加分号 `;`)
show warnings;
explain 能够干什么
-
读取表的顺序 -
哪些索引能够被使用 -
数据读取操作的操作类型 -
哪些索引能够被实际使用 -
表之间的引用 -
每张表有多少行被物理查询
具体的字段解读
使用 explain 之后,会返回如下各种信息。其中最重要的 5 个字段是:id、type、key、rows、Extra
那么我们依次详细解释每个字段的含义:
-
id:select 查询的序列号,包含一组数字,表示查询中执行 select 子句或操作表的顺序。
会出现如下三种可能:
-
id 相同,则表示执行顺序由上至下。 -
id 不同,如果是子查询,则表示 id 的序号会递增。id 值越大优先级越高,越先被执行。 -
id 有相同也有不同的,id 值越大优先级越高越先被执行,id 值相同的按由上到下执行。
-
select_type:查询的类型,主要是用于区别普通查询,联合查询,子查询等的复杂查询
大致会有如下几种结果:
-
simple :简单的 select 查询,查询中不包含子查询或者 union 语句。 -
primary :查询中若包含任何复杂的子查询部份,那么最外层查询则被标记为 primary -
subquery :在 select 或 where 列表中包含子查询语句。 -
derived :在 from 列表中包含的子查询被标记为 derived(衍生)MySQL 会递归执行这些子查询,把结果放在临时表里。 -
union :若第二个 select 出现在 union 之后,则被标记为 union
,若 union 包含在 from 子句的子查询中,外层 select 将被标记为derived
-
union result :从 union 表获取结果的 select
-
table :显示这一行的数据是关于哪张表的
-
type :访问类型排序 -
常用的从最好到最差依次是,system > const > eq_ref > ref > range > index > ALL -
完整的从最好到最差依次是 system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > ALL -
一般来说, 得保证查询至少达到 range 级别,最好能达到 ref 级别
下面是 type 字段可能出现的一些值。
-
system :表只有一行记录(等于系统表),这是 const 类型的特例,平时不会出现,这个也可以忽略不计。 -
const :表示通过索引一次就找到了,const 用于比较 primary key 或者 unique 索引。因为只匹配一行数据,所以很快。如将主键置于 where 列表中,MySQL 就能将该查询转换为一个常量 -
eq_ref : 唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描。 -
ref :非唯一性索引扫描,返回匹配某个单独值的所有行,本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体。 -
range :只检索给定范围的行,使用一个索引来选择行,key 列显示使用了哪个索引,一般就是在你的 where 语句中出现了 between 、< 、> 、in 等的查询。这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束于另一点,不用扫描全部索引 -
index :Full Index Scan,Index 与 ALL 区别为 index 类型只遍历索引树。这通常比 ALL 快,因为索引文件通常比数据文件小。(也就是说虽然 all 和 index 都是读全表,但 index 是从索引中读取的,而 all 是从硬盘中读的) -
all :Full Table Scan,将遍历全表以找到匹配的行
一般来说,得保证查询至少达到 range 级别,最好能达到 ref
-
possible_keys :显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用 这一点尤其要注意。
-
key :实际使用的索引。如果为 null,则没有使用索引。查询中若使用了覆盖索引,则该索引仅出现在 key 列表中。
-
key_len : 表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。在不损失精确性的情况下,长度越短越好。key_len 显示的值为索引字段的最大可能长度,并非实际使用长度,即 key_len 是根据表定义计算而得,不是通过表内检索出的
-
ref :显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值
-
rows :根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数(行数越小越好)
-
Extra :包含不适合在其它列中显示但十分重要的额外信息
下面是一些 Extra 可能会出现的一些值。
-
Using filesort :说明 mysql 会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL 中无法利用索引完成的排序操作称为“文件排序”。九死一生了,效率比较差 -
Using temporary :使用了临时表保存中间结果,MySQL 在对查询结果排序时使用临时表。常用于排序 order by 和分组查询 group by。可以说得上就是 十死无生,效率最差! -
Using index :表示相应的 select 操作中使用了覆盖索引(Covering index),避免访问了表的数据行,效率不错!如果同时出现 using where ,表明索引被用来执行索引键值的查找;如果没有同时出现 using where ,表明索引用来读取数据而非执行查找动作。 -
Using where :表明使用了 where 过滤 -
using join buffer :使用了连接缓存 -
impossible where :where 子句的值总是 false,不能用来获取任何元组 -
select tables optimized away :在没有 group by 子句的情况下,基于索引优化 min/max 操作或者对于 MyISAM 存储引擎优化 count(*) 操作,不必等到执行阶段再进行计算,查询执行计划生成的阶段即完成优化。 -
distinct :优化 distinct 操作,在找到第一匹配的元组后即停止找同样值的动作
好了,今天的分享就到这里了,下一篇会继续介绍其他的检测 MySQL 效率的方式,敬请期待。
最后说个事
公号算法变了,为防止看不到我的更新
大家帮忙加个星标
点击上方的公众号卡片
再点右上角三个点
就能看到设为星标
算我跪下来求你们
作者简介:
95后某跨境电商企业程序猿,白天搬砖码代码,晚上自媒体写文章,持续更新编程、科技、互联网相关文章,偶尔也会无痛呻吟,感慨人生百态。自己淋过雨,所以也想为别人撑撑伞。
往期精选:
原文始发于微信公众号(浅墨觅尘往):MySQL 性能分析大杀器(第一章)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/222111.html