快速学会分析SQL执行效率(下)
当你做成功一件事,千万不要等待着享受荣誉,应该再做那些需要的事。——巴斯德
在上一节我们学习了定位慢SQL及使用explain分析慢SQL,我们也提到了分析慢SQL还有showprofile和trace等方法,本节就重点补充学习这两种方法。
1、show profile分析慢查询
有时需要确定SQL到底慢在哪个环节,此时explain可能不好确定。在MySQL数据库中,通过profile,能够更清楚地了解SQL执行过程的资源使用情况,能让我们知道到底慢在哪个环节。
知识扩展:
可以通过配置参数 profiling = 1 来启用 SQL 分析。该参数可以在全局和 session 级别来设置。对于全局级别则作用于整个MySQL 实例,而 session 级别仅影响当前 session 。该参数开启后,后续执行的SQL 语句都将记录其资源开销,如 IO、上下文切换、CPU、Memory等等。根据这些开销进一步分析当前SQL 从而进行优化与调整。
下面我们来讲一下如何使用 profile 分析慢查询,大致步骤是:确定这个 MySQL 版本是否支持 profile;确定 profile是否关闭;开启 profile;执行 SQL;查看执行完 SQL 的 query id;通过 query id 查看 SQL 的每个状态及耗时时间。
下面是建表语句:
CREATE DATABASE muke;/* 创建测试使用的database,名为muke */
use muke;/* 使用muke这个database */
drop table if exists t1;/* 如果表t1存在则删除表t1 */
/* 创建表t1 */
CREATE TABLE `t1` (
`id` int(11) NOT NULL auto_increment,
`a` int(11) DEFAULT NULL,
`b` int(11) 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_a` (`a`),
KEY `idx_b` (`b`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
drop procedure if exists insert_t1; /* 如果存在存储过程insert_t1,则删除 */
delimiter ;;
create procedure insert_t1()
begin
/* 创建存储过程insert_t1 */
declare i int; /* 声明变量i */
set i=1; /* 设置i的初始值为1 */
while(i<=1000)do /* 对满足i<=1000的值进行while循环 */
insert into t1(a,b) values(i, i); /* 写入表t1中a、b两个字段,值都为i当前的值 */
set i=i+1; /* 将i加1 */
end while;
end;;
delimiter ; /* 创建批量写入1000条数据到表t1的存储过程insert_t1 */
call insert_t1(); /* 运行存储过程insert_t1 */
drop table if exists t2; /* 如果表t2存在则删除表t2 */
create table t2 like t1; /* 创建表t2,表结构与t1一致 */
insert into t2 select * from t1; /* 将表t1的数据导入到t2 */
1.1 确定是否支持 profile
我们进行第一步,用下面命令来判断当前 MySQL 是否支持 profile:
select @@have_profiling;
从上面结果中可以看出是YES,表示支持profile的。
1.2 查看 profiling 是否关闭的
进行第二步,用下面命令判断 profiling 参数是否关闭(默认 profiling 是关闭的):
select @@profiling;
我之前开启了所以是1,默认的结果是为 0,表示 profiling 参数状态是关闭的。
1.3 通过 set 开启 profile
set profiling=1;
Tips:set 时没加 global,只对当前 session 有效。
1.4 执行 SQL 语句
select * from t1 where b=1000;
1.5 确定 SQL 的 query id
通过 show profiles 语句确定执行过的 SQL 的 query id:
show profiles;
1.6 查询 SQL 执行详情
通过 show profile for query 可看到执行过的 SQL 每个状态和消耗时间:
show profile for query 1;
通过以上结果,可以确定 SQL 执行过程具体在哪个过程耗时比较久,从而更好地进行 SQL 优化与调整。
2 trace 分析 SQL 优化器
从前面学到了 explain 可以查看 SQL 执行计划,但是无法知道它为什么做这个决策,如果想确定多种索引方案之间是如何选择的或者排序时选择的是哪种排序模式,有什么好的办法吗?
从 MySQL 5.6 开始,可以使用 trace 查看优化器如何选择执行计划。
通过trace,能够进一步了解为什么优化器选择A执行计划而不是选择B执行计划,或者知道某个排序使用的排序模式,帮助我们更好地理解优化器行为。
如果需要使用,先开启 trace,设置格式为 JSON,再执行需要分析的 SQL,最后查看 trace 分析结果(在information_schema.OPTIMIZER_TRACE 中)。
开启该功能,会对 MySQL 性能有所影响,因此只建议分析问题时临时开启。
下面一起来看下 trace 的使用方法。使用讲解 explain 时创建的表t1做实验。
首先构造如下 SQL (表示取出表 t1 中 a 的值大于