一、Performance Schema 简介
Performance Schema 是 MySQL 中的一个工具,用于分析和监控 MySQL 数据库的性能问题。Performance Schema 采用了一种事件捕获和记录的方式,可以记录 MySQL 数据库中发生的各种事件,例如查询、锁等事件,以及事件的执行时间、等待时间等信息,从而可以通过分析这些事件信息来诊断数据库的性能问题。
二、启用 Performance Schema
在使用 Performance Schema 之前,需要在 MySQL 数据库中启用 Performance Schema。可以通过以下命令查看 MySQL 是否启用了 Performance Schema:
mysql> SHOW VARIABLES LIKE 'performance_schema';
如果结果为 ON,则表示 MySQL 已经启用了 Performance Schema。如果结果为 OFF,则需要在 MySQL 配置文件中启用 Performance Schema。
在配置文件中,将 performance_schema 参数设置为 ON,如下所示:
[mysqld]
performance_schema = ON
重启 MySQL 服务,使配置文件生效。
三、配置 Performance Schema
在 Performance Schema 启用后,需要配置 Performance Schema,以满足具体的性能分析需求。可以通过以下命令查看 Performance Schema 的配置:
mysql> SHOW VARIABLES LIKE 'performance_schema%';
可以根据具体需求,修改 Performance Schema 的配置参数。例如,可以将 performance_schema_events_waits_history_size 参数设置为 1000,以记录更多的等待事件历史记录:
mysql> SET GLOBAL performance_schema_events_waits_history_size = 1000;
四、分析SQL响应时间过长的问题
在 Performance Schema 启用和配置完成后,可以通过 Performance Schema 分析 MySQL 数据库的性能问题。例如,可以分析SQL线程响应时间过长的问题。可以通过以下命令查看哪类SQL平均响应时间最长:
mysql> SELECT SCHEMA_NAME,DIGEST_TEXT,AVG_TIMER_WAIT,FIRST_SEEN,LAST_SEEN FROM performance_schema.events_statements_summary_by_digest order by AVG_TIMER_WAIT desc limit 10;
该命令将列出响应时间最长的前 10 条SQL文本,可以通过该命令查看哪些SQL占用了较多的响应时间,从而可以对这些SQL进行分析并优化。
五、实验
使用sysbench创建测试表,并写入1000w行数据
sysbench --mysql-host=XXX --mysql-port=XXX --mysql-user=XXX --mysql-password=XXX --mysql-db=teletest --mysql-storage-engine=innodb --tables=1 --table-size=10000000 --time=180 --events=0 --report-interval=10 --rand-type=uniform --db-driver=mysql --percentile=95 oltp_read_write --forced-shutdown=off --threads=48 prepare
查看表是否写入成功。
mysql> select count(*) from sbtest1;
+----------+
| count(*) |
+----------+
| 10000000 |
+----------+
1 row in set (0.34 sec)
执行查询
mysql> select * from sbtest1 where pad like '66321586045%';
查看响应时间最长的SQL线程信息,记录了这条SQL的degest文本:
mysql> SELECT SCHEMA_NAME,DIGEST_TEXT,AVG_TIMER_WAIT,FIRST_SEEN,LAST_SEEN FROM performance_schema.events_statements_summary_by_digest where DIGEST_TEXT like 'SELECT%' order by AVG_TIMER_WAIT desc limit 10 \G
*************************** 1. row ***************************
SCHEMA_NAME: teletest
DIGEST_TEXT: SELECT * FROM `sbtest1` WHERE `pad` LIKE ?
AVG_TIMER_WAIT: 2490493844000
FIRST_SEEN: 2023-04-19 08:32:48.024789
LAST_SEEN: 2023-04-19 09:06:54.754311
对该SQL解析,全表扫描,没有索引
mysql> explain select * from sbtest1 where pad like '66321586045%';
+----+-------------+---------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| 1 | SIMPLE | sbtest1 | NULL | ALL | NULL | NULL | NULL | NULL | 9800580 | 11.11 | Using where |
+----+-------------+---------+------------+------+---------------+------+---------+------+---------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
因此针对这条SQL的pad字段添加索引:
mysql> alter table sbtest1 add index idx(pad);
Query OK, 0 rows affected (1 min 39.49 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql>
mysql> explain select * from sbtest1 where pad like '66321586045%';
+----+-------------+---------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+
| 1 | SIMPLE | sbtest1 | NULL | range | idx | idx | 240 | NULL | 1 | 100.00 | Using index condition |
+----+-------------+---------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)
添加索引后rows扫描的行数变为1,不再是全表扫描。