【MySQL高级】——性能分析

  数据库调优中,目标是 响应时间更快,吞吐量更大,利用宏观的监控工具和微观的日志分析帮助我们快速找到调优的思路和方式。

1. 数据库服务器优化步骤

  整个流程划分成了 观察(Show status) 和 行动(Action) 两个部分。字母 S 的部分代表观察(会使 用相应的分析工具),字母 A 代表的部分是行动(对应分析可以采取的行动)。
【MySQL高级】——性能分析_第1张图片
【MySQL高级】——性能分析_第2张图片

2. 查看系统性能参数

  在MySQL中,可以使用 SHOW STATUS 语句查询一些MySQL数据库服务器的 性能参数 、 执行频率 。

SHOW [GLOBAL|SESSION] STATUS LIKE '参数';

一些常用的性能参数如下:

• Connections:连接MySQL服务器的次数。 
• Uptime:MySQL服务器的上线时间。 
• Slow_queries:慢查询的次数。 
• Innodb_rows_read:Select查询返回的行数 
• Innodb_rows_inserted:执行INSERT操作插入的行数 
• Innodb_rows_updated:执行UPDATE操作更新的行数 
• Innodb_rows_deleted:执行DELETE操作删除的行数 
• Com_select:查询操作的次数。 
• Com_insert:插入操作的次数。对于批量插入的 INSERT 操作,只累加一次。 
• Com_update:更新操作的次数。 
• Com_delete:删除操作的次数。

3. 统计SQL的查询成本:last_query_cost

【MySQL高级】——性能分析_第3张图片
【MySQL高级】——性能分析_第4张图片
【MySQL高级】——性能分析_第5张图片

4. 定位执行慢的SQL:慢日志查询

<1> 概述

【MySQL高级】——性能分析_第6张图片

<2> 开启slow_query_log (global参数)

查看是否开启
show variables like ‘%low_query_log%’;
【MySQL高级】——性能分析_第7张图片
开启命令
set global slow_query_log=‘ON’;
【MySQL高级】——性能分析_第8张图片

<3> 修改long_query_time阈值(global&session参数)

1. 查看阈值

查看当前session

show variables like '%long_query_time%';

【MySQL高级】——性能分析_第9张图片
查看全局

show global variables like '%long_query_time%';

【MySQL高级】——性能分析_第10张图片

2. 设置阈值命令

全局设置

set global long_query_time = 1;

当前session

set long_query_time = 1;

3. min_examined_row_limit

【MySQL高级】——性能分析_第11张图片

<4> 查看慢查询数目

执行一个耗时sql

select student_id,create_time, count(*) from student_info GROUP BY student_id ,create_time;
SHOW GLOBAL STATUS LIKE '%Slow_queries%';

<5> 读取慢查询日志文件

执行一个耗时sql

select student_id,create_time, count(*) from student_info GROUP BY student_id ,create_time;

在这里插入图片描述

<6> 慢查询日志分析工具:mysqldumpslow

在生产环境中,如果要手工分析日志,查找、分析SQL,显然是个体力活,MySQL提供了日志分析工具 mysqldumpslow 。

1. 语法

【MySQL高级】——性能分析_第12张图片
mysqldumpslow 命令的具体参数如下:

-a: 不将数字抽象成N,字符串抽象成S
-s: 是表示按照何种方式排序:
    c: 访问次数
    l: 锁定时间
    r: 返回记录
    t: 查询时间
    al:平均锁定时间
    ar:平均返回记录数
    at:平均查询时间 (默认方式)
    ac:平均查询次数
-t: 即为返回前面多少条的数据;
-g: 后边搭配一个正则匹配模式,大小写不敏感的;

2. 案例

<1>按照查询时间排序,查看前五条 SQL 语句

mysqldumpslow -s t -t 5 /var/lib/mysql/mysql202-slow.log

在这里插入图片描述
<2> 得到返回记录集最多的10个SQL

mysqldumpslow -s r -t 10 /var/lib/mysql/mysql202-slow.log

<3> 得到访问次数最多的10个SQL

mysqldumpslow -s c -t 10 /var/lib/mysql/mysql202-slow.log

<4> 得到按照时间排序的前10条里面含有左连接的查询语句

mysqldumpslow -s t -t 10 -g "left join" /var/lib/mysql/mysql202-slow.log

<5> 另外建议在使用这些命令时结合 | 和more 使用 ,否则有可能出现爆屏情况

mysqldumpslow -s r -t 10 /var/lib/mysql/mysql202-slow.log | more

<7> 关闭慢查询日志

1. 配置文件(永久性)

设置为OFF

[mysqld] 
slow_query_log=OFF

或直接删除或注释

[mysqld] 
#slow_query_log =OFF

2. 命令方式(临时性)

SET GLOBAL slow_query_log=off;

<8> 删除慢查询日志

  1. 查询文件位置,然后去文件目录中删除或备份即可
  2. 重新生成日志文件:mysqladmin -uroot -p flush-logs slow

5. 查看SQL执行成本:profiler(global&session参数)

<1> 查看状态

全局设置

show global variables like 'profiling';

【MySQL高级】——性能分析_第13张图片
当前session

show variables like 'profiling';

<2> 开启关闭

全局设置

set global profiling = 'ON';

当前session

set profiling = 'ON';

<3> 查看sql列表

show profiles;

【MySQL高级】——性能分析_第14张图片

<4> 查看最近一个sql详细内容

show profile;

【MySQL高级】——性能分析_第15张图片

<5> 查看指定请求详细内容

show profile for query 2;

【MySQL高级】——性能分析_第16张图片

<6> 常用查询参数

  1. ALL:显示所有的开销信息。
  2. BLOCK IO:显示块IO开销。
  3. CONTEXT SWITCHES:上下文切换开销。
  4. CPU:显示CPU开销信息。
  5. IPC:显示发送和接收开销信息。
  6. MEMORY:显示内存开销信息。
  7. PAGE FAULTS:显示页面错误开销信息。
  8. SOURCE:显示和Source_function,Source_file,Source_line相关的开销信息。
  9. SWAPS:显示交换次数开销信息。
    【MySQL高级】——性能分析_第17张图片

<7> 注意

【MySQL高级】——性能分析_第18张图片

6. 分析查询语句:EXPLAIN

<1> 概述

1. 简介

【MySQL高级】——性能分析_第19张图片

2. 作用

【MySQL高级】——性能分析_第20张图片

3. 版本情况

【MySQL高级】——性能分析_第21张图片

<2> 基本语法

  1. 语法
EXPLAIN SELECT select_options 

或者

DESCRIBE SELECT select_options
  1. 案例
EXPLAIN SELECT 1;

<3> 数据准备

依次执行

CREATE TABLE s1 (
id INT AUTO_INCREMENT,
key1 VARCHAR(100),
key2 INT,
key3 VARCHAR(100),
key_part1 VARCHAR(100),
key_part2 VARCHAR(100),
key_part3 VARCHAR(100),
common_field VARCHAR(100),
PRIMARY KEY (id),
INDEX idx_key1 (key1),
UNIQUE INDEX idx_key2 (key2),
INDEX idx_key3 (key3),
INDEX idx_key_part(key_part1, key_part2, key_part3)
) ENGINE=INNODB CHARSET=utf8;

CREATE TABLE s2 (
id INT AUTO_INCREMENT,
key1 VARCHAR(100),
key2 INT,
key3 VARCHAR(100),
key_part1 VARCHAR(100),
key_part2 VARCHAR(100),
key_part3 VARCHAR(100),
common_field VARCHAR(100),
PRIMARY KEY (id),
INDEX idx_key1 (key1),
UNIQUE INDEX idx_key2 (key2),
INDEX idx_key3 (key3),
INDEX idx_key_part(key_part1, key_part2, key_part3)
) ENGINE=INNODB CHARSET=utf8;

set global log_bin_trust_function_creators=1;

DELIMITER //
CREATE FUNCTION rand_string1(n INT)
RETURNS VARCHAR(255) #该函数会返回一个字符串
BEGIN
DECLARE chars_str VARCHAR(100) DEFAULT
'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
DECLARE return_str VARCHAR(255) DEFAULT '';
DECLARE i INT DEFAULT 0;
WHILE i < n DO
SET return_str =CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
SET i = i + 1;
END WHILE;
RETURN return_str;
END //
DELIMITER ;

DELIMITER //
CREATE PROCEDURE insert_s1 (IN min_num INT (10),IN max_num INT (10))
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i + 1;
INSERT INTO s1 VALUES(
(min_num + i),
rand_string1(6),
(min_num + 30 * i + 5),
rand_string1(6),
rand_string1(10),
rand_string1(5),
rand_string1(10),
rand_string1(10));
UNTIL i = max_num
END REPEAT;
COMMIT;
END //
DELIMITER ;

DELIMITER //
CREATE PROCEDURE insert_s2 (IN min_num INT (10),IN max_num INT (10))
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i + 1;
INSERT INTO s2 VALUES(
(min_num + i),
rand_string1(6),
(min_num + 30 * i + 5),
rand_string1(6),
rand_string1(10),
rand_string1(5),
rand_string1(10),
rand_string1(10));
UNTIL i = max_num
END REPEAT;
COMMIT;
END //
DELIMITER ;

CALL insert_s1(10001,10000);

CALL insert_s2(10001,10000);

<4> EXPLAIN 输出列详解

【MySQL高级】——性能分析_第22张图片

1. table

在这里插入图片描述
【MySQL高级】——性能分析_第23张图片

2. id

在这里插入图片描述

同一组中,排在上边的就做驱动表,后边的叫做 被驱动表

【MySQL高级】——性能分析_第24张图片

3. select_type

【MySQL高级】——性能分析_第25张图片

【MySQL高级】——性能分析_第26张图片

<1> SIMPLE

查询语句中不包含UNION或者子查询的查询都算作是SIMPLE类型
连接查询也算是SIMPLE类型

<2> PRIMARY

对于包含UNION或者UNION ALL或者子查询的大查询来说,它是由几个小查询组成的,其中最左边的那个查询的select_type值就是PRIMARY

<3> UNION

对于包含UNION或者UNION ALL的大查询来说,它是由几个小查询组成的,其中除了最左边的那个小查询以外,其余的小查询的select_type值就是UNION

<4> UNION RESULT

MySQL选择使用临时表来完成UNION查询的去重工作,针对该临时表的查询的select_type就是UNION RESULT
在这里插入图片描述
在这里插入图片描述

<5> SUBQUERY

如果包含子查询的查询语句不能够转为对应的semi-join的形式,并且该子查询是不相关子查询。该子查询的第一个SELECT关键字代表的那个查询的select_type就是SUBQUERY

<6> DEPENDENT SUBQUERY

如果包含子查询的查询语句不能够转为对应的semi-join的形式,并且该子查询是相关子查询,则该子查询的第一个SELECT关键字代表的那个查询的select_type就是DEPENDENT SUBQUERY , select_type为DEPENDENT SUBQUERY的查询可能会被执行多次。
在这里插入图片描述
在这里插入图片描述

<7> DEPENDENT UNION

在包含UNION或者UNION ALL的大查询中,如果各个小查询都依赖于外层查询的话,那除了最左边的那个小查询之外,其余的小查询的select_type的值就是DEPENDENT UNION

在这里插入图片描述
在这里插入图片描述

<8> DERIVED

对于包含派生表的查询,该派生表对应的子查询的select_type就是DERIVED

在这里插入图片描述

在这里插入图片描述

<9> MATERIALIZED

当查询优化器在执行包含子查询的语句时,选择将子查询物化之后与外层查询进行连接查询时,该子查询对应的select_type属性就是MATERIALIZED

在这里插入图片描述
在这里插入图片描述

4. partitions

在这里插入图片描述

5. type

【MySQL高级】——性能分析_第27张图片
【MySQL高级】——性能分析_第28张图片

<1> system

当表中只有一条记录并且该表使用的存储引擎的统计数据是精确的,比如MyISAM、Memory,那么对该表的访问方法就是system
【MySQL高级】——性能分析_第29张图片

<2> const

当我们根据主键或者唯一二级索引列与常数进行等值匹配时,对单表的访问方法就是const

【MySQL高级】——性能分析_第30张图片

<3> eq_ref

在连接查询时,如果被驱动表是通过主键或者唯一二级索引列等值匹配的方式进行访问的(如果该主键或者唯一二级索引是联合索引的话,所有的索引列都必须进行等值比较),则对该被驱动表的访问方法就是eq_ref

在这里插入图片描述

<4> ref

当通过普通的二级索引列与常量进行等值匹配时来查询某个表,那么对该表的访问方法就可能是ref
在这里插入图片描述

<5> ref_or_null

当对普通二级索引进行等值匹配查询,该索引列的值也可以是NULL值时,那么对该表的访问方法就可能是ref_or_null
在这里插入图片描述

<6> index_merge

单表访问方法时在某些场景下可以使用IntersectionUnionSort-Union这三种索引合并的方式来执行查询

在这里插入图片描述

<7> unique_subquery

unique_subquery是针对在一些包含IN子查询的查询语句中,如果查询优化器决定将IN子查询转换为EXISTS子查询,而且子查询可以使用到主键进行等值匹配的话,那么该子查询执行计划的type列的值就是unique_subquery

在这里插入图片描述

<8> range

如果使用索引获取某些范围区间的记录,那么就可能使用到range访问方法
在这里插入图片描述

<9> index

当我们可以使用索引覆盖,但需要扫描全部的索引记录时,该表的访问方法就是index

在这里插入图片描述

<10>all

全表扫描

6. possible_keys 和key

在这里插入图片描述

7. key_len

实际使用到的索引长度(即:字节数),帮助检查是否充分利用上了索引,值越大越好,主要针对于联合索引,有一定参考意义。

<1> key_len的长度计算公式
  1. varchar(10)变长字段且允许NULL
    10 * ( character set:utf8=3,gbk=2,latin1=1)+1(NULL)+2(变长字段)
  2. varchar(10)变长字段且不允许NULL
    10 * ( character set:utf8=3,gbk=2,latin1=1)+2(变长字段)
  3. char(10)固定字段且允许NULL
    10 * ( character set:utf8=3,gbk=2,latin1=1)+1(NULL)
  4. char(10)固定字段且不允许NULL
    10 * ( character set:utf8=3,gbk=2,latin1=1)

8. ref

当使用索引列等值查询时,与索引列进行等值匹配的对象信息。比如只是一个常数或者是某个列。

9. rows

预估的需要读取的记录条数 ,值越小越好

10. filtered

某个表经过搜索条件过滤后剩余记录条数的百分比如果使用的是索引执行的单表扫描,那么计算时需要估计出满足除使用到对应索引的搜索条件外的其他搜索条件的记录有多少条。

你可能感兴趣的:(mysql,mysql,数据库)