如何利用工具,迅猛定位低效 SQL? | 1 分钟系列

摘抄自:https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651961957&idx=1&sn=c4cdf7c27ade9c95fdf40c4c38e19da9&chksm=bd2d0fb98a5a86af13ec7f096bde37e1c8cd0d19e7124e6bdb53761314d5b64a39ba9fbd1355&scene=21#wechat_redirect

详细叙述了 explain 结果中最重要的 type 字段(连接类型)的含义。

其实,explain 结果中还有一个 Extra 字段,对分析与优化 SQL 有很大的帮助,今天花 1 分钟简单和大家聊一聊。

数据准备

create table user (

id int primary key_,_

name varchar(20),

sex varchar(5),

index(name)

)engine=innodb;

insert into user values(1, 'shenjian','no');

insert into user values(2, 'zhangsan','no');

insert into user values(3, 'lisi','yes');

insert into user values(4, 'lisi','no');

数据说明

用户表:id 主键索引,name 普通索引(非唯一),sex 无索引

四行记录:其中 name 普通索引存在重复记录 lisi;

实验目的

通过构造各类 SQL 语句,对 explain 的 Extra 字段进行说明,启发式定位待优化低性能 SQL 语句。

一、【Using where】

实验语句

explain select * from user where sex='no';

结果说明

Extra 为 Using where 说明,SQL 使用了 where 条件过滤数据。

需要注意的是:

(1)返回所有记录的 SQL,不使用 where 条件过滤数据,大概率不符合预期,对于这类 SQL 往往需要进行优化;

(2)使用了 where 条件的 SQL,并不代表不需要优化,往往需要配合 explain 结果中的 type(连接类型)来综合判断;

画外音:join type 在《同一个 SQL 语句,为啥性能差异咋就这么大呢?》一文中有详细叙述,本文不再展开。

本例虽然 Extra 字段说明使用了 where 条件过滤,但 type 属性是 ALL,表示需要扫描全部数据,仍有优化空间。

常见的优化方法为,在 where 过滤属性上添加索引。

_画外音:_本例中,sex 字段区分度不高,添加索引对性能提升有限。

二、【Using index】

实验语句

explain select id,name from user where name='shenjian';

结果说明

Extra 为 Using index 说明,SQL 所需要返回的所有列数据均在一棵索引树上,而无需访问实际的行记录。

_画外音:_The column information is retrieved from the table using only information in the index tree without having to do an additional seek to read the actual row.

这类 SQL 语句往往性能较好。

问题来了,什么样的列数据,会包含在索引树上呢?

三、【Using index condition】

实验语句:

explain select id,name,sex from user

where name='shenjian';

_画外音:_该 SQL 语句与上一个 SQL 语句不同的地方在于,被查询的列,多了一个 sex 字段。

结果说明:

Extra 为 Using index condition 说明,确实命中了索引,但不是所有的列数据都在索引树上,还需要访问实际的行记录。

画外音:聚集索引,普通索引的底层实现差异,详见《1 分钟了解 MyISAM 与 InnoDB 的索引差异》。

这类 SQL 语句性能也较高,但不如 Using index。

问题来了,如何优化为 Using index 呢?

四、【Using filesort】

实验语句:

explain select * from user order by sex;

结果说明:

Extra 为 Using filesort 说明,得到所需结果集,需要对所有记录进行文件排序。

这类 SQL 语句性能极差,需要进行优化。

典型的,在一个没有建立索引的列上进行了 order by,就会触发 filesort,常见的优化方案是,在 order by 的列上添加索引,避免每次查询都全量排序。

五、【Using temporary】

实验语句:

explain select * from user group by name order by sex;

结果说明:

Extra 为 Using temporary 说明,需要建立临时表 (temporary table) 来暂存中间结果。

这类 SQL 语句性能较低,往往也需要进行优化。

典型的,group by 和 order by 同时存在,且作用于不同的字段时,就会建立临时表,以便计算出最终的结果集。

六、【Using join buffer (Block Nested Loop)】

实验语句:

explain select * from user where id in(select id from user where sex='no');

结果说明:

Extra 为 Using join buffer (Block Nested Loop) 说明,需要进行嵌套循环计算。

_画外音:_内层和外层的 type 均为 ALL,rows 均为 4,需要循环进行 4*4 次计算。

这类 SQL 语句性能往往也较低,需要进行优化。

典型的,两个关联表 join,关联字段均未建立索引,就会出现这种情况。常见的优化方案是,在关联字段上添加索引,避免每次嵌套循环计算。

结尾

explain 是 SQL 优化中最常用的工具,搞定 type 和 Extra,explain 也就基本搞定了


作者:58沈剑_架构师之路
链接:https://juejin.cn/post/6903715978132078606
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原文地址:https://www.cnblogs.com/shujiying/p/14187773.html