MySQL性能调优实战手册:从慢查询到执行计划全解析

一、调优流程四步走 🚀

当我们遇到数据库调优问题的时候,该如何思考呢?
这里把思考的流程整理成下面这张图。
整个流程划分成了观察(Show status)行动(Action)两个部分。字母S的部分代表观察(会使用相应的分析工具),字母A代表的部分是行动(对应分析可以采取的行动)。

  • 周期性波动:双十一/促销活动导致流量激增,需提前扩容
  • 突发性能问题:用 SHOW STATUS 定位瓶颈(如慢查询暴增)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    小结
    在这里插入图片描述

二、性能监控三板斧 🔍

1️⃣ 系统性能参数速查

--查看sql执行频次,如果查询占比较高,需要进行下一步的优化动作。
SHOW  [GLOBAL|SESSION] STATUS LIKE '参数'

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

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

2️⃣ 查询成本分析 last_query_cost

在执行 SQL 查询前,MySQL 确定执行计划并计算其成本,选择成本最低的计划。如果想查看某条 SQL 的查询成本,可以使用以下命令:

SHOW  STATUS LIKE 'last_query_cost'

这个成本通常与 SQL 语句读取的页数相关,是评估查询效率的常用指标。在这里插入图片描述

使用场景

  • 位置决定效率:数据页在数据库缓冲池中时效率最高;若不在,则需从内存或磁盘读取,内存读取显著更快。
    批量决定效率:单页随机读取效率低(约 10ms),而顺序读取多页效率更高,甚至优于内存中的随机读取。
    优化建议
  • 将常用数据放入缓冲池。
  • 利用磁盘的吞吐能力,批量读取数据以提高单页读取效率。

3️⃣ 慢查询日志实战

1. 什么是慢查询日志?

  • 慢查询日志记录运行时间超过 long_query_time 阈值的 SQL 语句。默认情况下,long_query_time 为 10 秒,表示执行超时的 SQL 语句。

2. 主要作用:

  • 慢查询日志帮助识别执行时间长的查询,以便进行优化,提升系统效率。在数据库阻塞或变慢时,检查慢查询日志可以帮助定位问题。

3. 开启慢查询日志:
默认情况下,慢查询日志是关闭的。可以通过以下命令开启:

SHOW VARIABLES LIKE '%slow_query_log';  # 查看当前状态
SET GLOBAL slow_query_log = 'ON';  # 开启慢查询日志

4. 修改long_query_time:
设置阈值以记录更短时间的慢查询:

SET GLOBAL long_query_time = 1;  # 设置为1秒
SHOW GLOBAL VARIABLES LIKE '%long_query_time%';

要永久生效,可以在 /etc/my.cnf 中添加以下配置:

[mysqld]
slow_query_log=ON #开启慢查询日志的开关
slow_query_log_file=/var/lib/mysql/atguigu-slow.log #慢查询日志的目录和文件名信息,如果不指定文件名默认文件名为 hostname-slow.log。
long_query_time=3 #设置慢查询的阈值为3秒,超出此设定值的SQL即被记录到慢查询日志
log_output=FILE
# 如果不指定存储路径,慢查询日志将默认存储到MySQL数据库的数据文件夹下。

5. 查看慢查询记录
查询当前系统的慢查询条数:

SHOW GLOBAL STATUS LIKE '%slow_queries%';

6. 慢查询日志分析工具
使用 mysqldumpslow 命令分析慢查询日志:

mysqldumpslow -s t -t 5 /var/lib/mysql/atguigu05-slow.log  # 查看前5条

示例:
在这里插入图片描述

7. 关闭慢查询日志

  • 永久性关闭:修改配置文件,将 slow_query_log 设置为 OFF,然后重启 MySQL。
[mysqld]
slow_query_log=OFF  # 注释也可

- 临时关闭:

set global slow_query_log='OFF' 
  1. 删除慢查询日志
    手动删除慢查询日志文件,或使用以下命令重新生成日志:
mysqladmin -uroot -p flush-logs slow

注意:慢查询日志的目录(/var/lib/mysql/xx.log)默认为MySQL的数据目录,执行此命令后,旧日志将被替换,建议提前备份。

三:SQL解剖刀:EXPLAIN执行计划 🔧

在定位慢查询后,可以使用 EXPLAINDESCRIBE 工具分析 SQL 语句的执行计划。EXPLAIN 展示查询的执行方式,包括多表连接顺序及访问方法。

1. 能做什么?

  • 表的读取顺序
  • 数据读取操作类型
  • 可用的索引
  • 实际使用的索引
  • 表之间的引用
  • 每张表优化后的行数

2. 官网介绍
https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
https://dev.mysql.com/doc/refman/8.0/en/explain-output.html

3. 版本情况

  • 查看某个查询的执行计划,可以在具体的查询语句前加一个 EXPLAIN
  • MySQL 5.6.3 之前只能对 SELECT 使用 EXPLAIN;之后支持对 UPDATE 和 DELETE。
  • 在5.7以前的版本中,想要显示partitions需要使用explain partitions 命令;想要显示filtered需要使用explain extended命令。在5.7版本后,默认explain直接显示partitions和filtered中的信息
    tip: 执行EXPLAIN时并没有真正的执行该后面的语句,因此可以安全的查看执行计划.

基本语法

EXPLAIN/DESCRIBE select/delete/update/insert ... ...

4. EXPLAIN各列作用

1. table 表名

查询的每一行记录对应一个表。

#s1: 驱动表  s2: 被驱动表
EXPLAIN SELECT * FROM s1 INNER JOIN s2;

tip: 表名可以是别名或临时表。

2. id 查询标识,标识执行顺序

标识执行顺序。

  • 相同的 id 值表示同组查询,按照从上到下的顺序执行。
  • 在同一组中,id值越大,优先级越高,越先执行
  • 关注点: id号每个号码,表示一趟独立的查询,一个sql的查询趟数越少越好
    在这里插入图片描述在这里插入图片描述在这里插入图片描述

3. select_type 查询类型

  • SIMPLE:简单查询,无 UNION 或子查询。
  • PRIMARY:最外层查询。
  • UNION:后续的 UNION 查询。
  • SUBQUERY:子查询。
  • DEPENDENT UNION:依赖外部查询的 UNION。
  • DERIVED:派生表查询。
#查询语句中不包含`UNION`或者子查询的查询都算作是`SIMPLE`类型
 EXPLAIN SELECT * FROM s1;
#连接查询也算是`SIMPLE`类型
 EXPLAIN SELECT * FROM s1 INNER JOIN s2;

 
 #对于包含`UNION`或者`UNION ALL`或者子查询的大查询来说,它是由几个小查询组成的,其中最左边的那个查询的`select_type`值就是`PRIMARY`,
 其中除了最左边的那个小查询以外,其余的小查询的`select_type`值就是`UNION`
 
 
 #`MySQL`选择使用临时表来完成`UNION`查询的去重工作,针对该临时表的查询的`select_type`就是
`UNION RESULT`
 EXPLAIN SELECT * FROM s1 UNION SELECT * FROM s2;
 

 #子查询:如果包含子查询的查询语句不能够转为对应的`semi-join`的形式,并且该子查询是不相关子查询, 则该子查询的第一个`SELECT`关键字代表的那个查询的`select_type`就是`SUBQUERY`
 EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2) OR key3 = 'a';
 
# 如果包含子查询的查询语句不能够转为对应的`semi-join`的形式,并且该子查询是相关子查询,
 则该子查询的第一个`SELECT`关键字代表的那个查询的`select_type`就是`DEPENDENT SUBQUERY`
 EXPLAIN SELECT * FROM s1 
 WHERE key1 IN (SELECT key1 FROM s2 WHERE s1.key2 = s2.key2) OR key3 = 'a';
  注意的是,select_type为`DEPENDENT SUBQUERY`的查询可能会被执行多次。
 
 
#在包含`UNION`或者`UNION ALL`的大查询中,如果各个小查询都依赖于外层查询的话,那除了最左边的那个小查询之外,其余的小查询的`select_type`的值就是`DEPENDENT UNION`。
 EXPLAIN SELECT * FROM s1 
 WHERE key1 IN (SELECT key1 FROM s2 WHERE key1 = 'a' UNION SELECT key1 FROM s1 WHERE key1 = 'b');
 
 
#对于包含`派生表`的查询,该派生表对应的子查询的`select_type`就是`DERIVED`
 EXPLAIN SELECT * 
 FROM (SELECT key1, COUNT(*) AS c FROM s1 GROUP BY key1) AS derived_s1 WHERE c > 1;
 
 
 #当查询优化器在执行包含子查询的语句时,选择将子查询物化之后与外层查询进行连接查询时,
 #该子查询对应的`select_type`属性就是`MATERIALIZED`
 EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2); #子查询被转为了物化表

4. partitions(可略)

匹配的分区信息

5. type(比较重要)

单表的访问方法,表示查询效率。

  • system:只有一条记录的系统表。
  • const:最多一条匹配记录,速度非常快。
  • eq_ref:每个组合的行读取,最佳类型。
  • ref:读取匹配索引值的所有行。
  • fulltext:使用 FULLTEXT 索引。
  • index_merge:使用索引合并。
  • ALL:全表扫描,通常效率最低。
    PS:越靠前越好
#当表中`只有一条记录`并且该表使用的存储引擎的统计数据是`精确`的,比如 MyISAM、Memory
特点:数据量较少,往往不需要磁盘IO,速度非常快
那么对该表的访问方法就是`system`。
 CREATE TABLE t(i INT) ENGINE=MYISAM;
 INSERT INTO t VALUES(1);
 
 EXPLAIN SELECT * FROM t;
 
 
 当我们根据`主键`或者`唯一二级索引列``常数`进行等值匹配时,对单表的访问方法就是`const`
 特点:扫描效率较高,返回数据量少,速度非常快
 EXPLAIN SELECT * FROM s1 WHERE id = 10005;

 
# 在连接查询时,如果`被驱动表`是通过`主键`或者`唯一二级索引列``等值匹配`的方式进行访问的
 (如果该主键或者唯一二级索引是联合索引的话,所有的索引列都必须进行等值比较),则对该被驱动表的访问方法就是`eq_ref`
 EXPLAIN SELECT * FROM student_info s INNER JOIN course c ON s.course_id = c.id;
 tip:id为course表的主键
  
  
 # 当通过普通的`二级索引列`与`常量`进行等值匹配时来查询某个表,那么对该表的访问方法就可能是`ref`
 特点:使用非唯一性索引,会找到多个符合条件的行
 EXPLAIN SELECT * FROM s1 WHERE key1 = 'a';
 
 
# 当对`普通二级索引`进行`等值`匹配查询,该索引列的值也可以是`NULL`值时,那么对该表的访问方法就可能是`ref_or_null`
 EXPLAIN SELECT * FROM s1 WHERE key1 = 'a' OR key1 IS NULL;
 
 
#  单表访问方法时在某些场景下可以使用`Intersection`、`Union`、
`Sort-Union`这三种索引合并的方式来执行查询,访问方式就是 `index_merge`(此时key1和keys都是索引)
 EXPLAIN SELECT * FROM s1 WHERE key1 = 'a' OR key3 = 'a';
 
 
# unique_subquery`是针对在一些包含`IN`子查询的查询语句中,如果查询优化器决定将`IN`子查询转换为`EXISTS`子查询, 而且子查询可以使用到主键进行等值匹配的话,那么该子查询执行计划的`type`列的值就是`unique_subquery`
 EXPLAIN SELECT * FROM s1 
 WHERE key2 IN (SELECT id FROM s2 WHERE s1.key1 = s2.key1) OR key3 = 'a';
 //value IN (SELECT primary_key FROM single_table WHERE some_expr)
 
 
# 如果使用`索引`获取某些`范围区间`的记录,那么就可能使用到`range`访问方法
 特点:使用`索引字段`在where语句中使用 bettween...and、<><=、in 等范围条件查询 type 都是 range。
 EXPLAIN SELECT * FROM s1 WHERE key1 IN ('a', 'b', 'c');
 
 #同上
 EXPLAIN SELECT * FROM s1 WHERE key1 > 'a' AND key1 < 'b';
 
 
 #当我们可以使用`索引覆盖`,但需要扫描全部的索引记录时,该表的访问方法就是`index`,遍历索引树读取。如下表(key_pat1, key_part2, key_part3)为联合索引,不用走全表扫描可完成查询
 EXPLAIN SELECT key_part2 FROM s1 where key_part3 = 'a';
 
 #最熟悉的全表扫描`ALL`,从磁盘中读取
 EXPLAIN SELECT * FROM s1;

小结:

  • 结果值从最好到最坏依次是:
    system > const > eq_ref > ref fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
  • SQL性能优化的目标:至少要达到range级别,要求是ref级别,最好是const级别。(阿里巴巴开发手册要求)

6. possible_keys 和 key

  • possible_keys:可能使用的索引,但不一定被查询使用。
  • key 列表示实际用到的索引有哪些,如果为NULL,则没有使用索引。

7.key_len

实际使用到的索引长度(单位:字节数),帮你检查,是否充分的利用上了索引,值越大越好(主要针对联合索引,有一定的参考意义)
tip:key_len只计算where条件中用到的索引长度

8.ref

当使用索引列等值查询时,与索引列进行等值匹配的对象信息,常见值有 const、func、null

  • 当使用常量等值查询,显示const
  • 当关联查询,显示相应关联表的关联字段
  • 当查询条件使用了表达式、函数,或者条件列发生内部隐式转换,可能显示为func

9.rows

估计需要读取的行数,值越小越好。

10. filtered

经过搜索条件过滤后的记录百分比,值越高越好

#如果使用的是索引执行的`单表`扫描,那么计算时需要估计出满足除使用到 对应索引的搜索条件外的其他搜索条件的记录有多少条。
EXPLAIN SELECT * FROM s1 WHERE key1 > 'z' AND common_field = 'a';

#对于单表查询来说,这个filtered列的值没什么意义,我们更关注在连接查询中驱动表对应的执行计划记录的filtered值,它决定了被驱动表要执行的次数(即:rows * filtered)
 EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s1.key1 = s2.key1 WHERE s1.common_field = 'a';

11. extra

额外信息,帮助理解查询执行情况。

 `No table Used`
#当查询语句的没有`FROM`子句时将会提示该额外信息 `No table Used`
 EXPLAIN SELECT 1;
 
  `Impossible WHERE`
 #查询语句的`WHERE`子句永远为`FALSE`时将会提示该额外信息 `Impossible WHERE`
 EXPLAIN SELECT * FROM s1 WHERE 1 != 1;

 `Using where`
 #1. 当我们使用`全表扫描`来执行对某个表的查询,并且该语句的`WHERE`子句中有针对该表的搜索条件时,在`Extra`列中会提示上述额外信息。`Using where`
 EXPLAIN SELECT * FROM s1 WHERE common_field = 'a';
 #2.当使用`索引`访问来执行对某个表的查询,并且该语句的`WHERE`子句中有除了该索引包含的列之外的其他搜索条件时,在`Extra`列中也会提示上述额外信息。`Using where`(key1为主键))
 EXPLAIN SELECT * FROM s1 WHERE key1 = 'a' AND common_field = 'a';
 
 
 #当查询列表处有`MIN`或者`MAX`聚合函数,但是并没有符合`WHERE`子句中的搜索条件的记录时,将会提示该额外信息 `No matching min/max row`
 EXPLAIN SELECT MIN(key1) FROM s1 WHERE key1 = 'abcdefg';
 #有记录时,提示 `Select table optimized away`
 EXPLAIN SELECT MIN(key1) FROM s1 WHERE key1 = 'NlPros'; # NlPros 是 s1表中key1字段真实存在的数据
 
 select * from s1 limit 10;
  
  `Using index`
 #当我们的查询列表以及搜索条件中只包含属于某个索引的列,也就是在可以使用`覆盖索引`的情况下,在`Extra`列将会提示该额外信息。
 比方说下边这个查询中只需要用到`idx_key1`而不需要回表操作, 提示`Using index`
 EXPLAIN SELECT idx_key1 FROM s1 WHERE key1 = 'a';
 
 
 #有些搜索条件中虽然出现了索引列,但却不能使用到索引
 #看课件理解`索引条件下推`,提示`Using index condition`
 EXPLAIN SELECT * FROM s1 WHERE key1 > 'z' AND key1 LIKE '%a';

 
 #在连接查询执行过程中,当被驱动表不能有效的利用索引加快访问速度,MySQL一般会为其分配一块名叫`join buffer`的内存块来加快查询速度,也就是我们所讲的`基于块的嵌套循环算法`,提示`Using where; Using join buffer(hash join)`
 EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s1.common_field = s2.common_field;
 
 
 #当我们使用左(外)连接时,如果`WHERE`子句中包含要求被驱动表的某个列等于`NULL`值的搜索条件, 而且那个列又是不允许存储`NULL`值的,那么在该表的执行计划的Extra列就会提示`Not exists`额外信息
 EXPLAIN SELECT * FROM s1 LEFT JOIN s2 ON s1.key1 = s2.key1 WHERE s2.id IS NULL;
 
 
 #如果执行计划的`Extra`列出现了`Using intersect(...)`提示,说明准备使用`Intersect`索引
 #合并的方式执行查询,括号中的`...`表示需要进行索引合并的索引名称;
 #如果出现了`Using union(...)`提示,说明准备使用`Union`索引合并的方式执行查询;
 #出现了`Using sort_union(...)`提示,说明准备使用`Sort-Union`索引合并的方式执行查询。
 EXPLAIN SELECT * FROM s1 WHERE key1 = 'a' OR key3 = 'a';(其中key1和keys都是单独的索引)
 
 
 #当我们的`LIMIT`子句的参数为`0`时,表示压根儿不打算从表中读出任何记录,将会提示该额外信息`Zero limit`
 EXPLAIN SELECT * FROM s1 LIMIT 0;
 
 `Using filesort` 
# 若排序操作无法使用到索引,只能在内存中(记录较少的时候)或者磁盘中(记录较多的时候)进行排序,MySQL把这种在内存中或者磁盘上进行排序的方式统称为`文件排序`(英文名:`filesort`)。也就是order by的字段没有索引
 EXPLAIN SELECT * FROM s1 ORDER BY common_field LIMIT 10;
 
 
  `Using temporary`
 #在许多查询的执行过程中,MySQL可能会借助`临时表`来完成一些功能,比如去重、排序之类的,比如我们在执行许多包含`DISTINCT`、`GROUP BY`、`UNION`等子句的查询过程中,如果不能有效利用索引来完成
查询,MySQL很有可能寻求通过建立内部的临时表来执行查询。如果查询中使用到了内部的临时表,在执行
 计划的`Extra`列将会显示`Using temporary`提示
 EXPLAIN SELECT DISTINCT common_field FROM s1;
 `Using temporary`
 EXPLAIN SELECT DISTINCT key1 FROM s1;
  `Using index`
 EXPLAIN SELECT common_field, COUNT(*) AS amount FROM s1 GROUP BY common_field;
 
 # 执行计划中出现`Using temporary`并不是一个好的征兆,因为建立与维护`临时表`要付出很大成本的,所以我们`最好能使用索引来替代掉使用临时表`。
 比如:扫描指定的索引idx_key1即可
 EXPLAIN SELECT key1, COUNT(*) AS amount FROM s1 GROUP BY key1;

小结

  • EXPLAIN不考虑各种cache
  • EXPLAIN不能显示MySQL在执行查询时所作的优化工作
  • EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况
  • 部分统计信息是估算的,并非精确值

5.EXPLAIN的进一步使用

EXPLAIN四种输出格式

EXPLAIN 可以输出四种格式:传统格式、JSON 格式、TREE 格式和可视化输出。用户可以根据需求选择适合的格式。

  1. 传统格式:默认的表格形式。
    在这里插入图片描述

  2. JSON 格式:提供最详尽的信息,包括执行成本。使用方法是在 EXPLAIN 和查询语句之间添加 FORMAT=JSON。

#json格式的explain
EXPLAIN FORMAT=JSON SELECT * FROM s1 INNER JOIN s2 ON s1.key1 = s2.key2 
WHERE s1.common_field = 'a';

在这里插入图片描述

3. TREE格式
自 8.0.16 版本引入,描述查询部分之间的关系执行顺序

EXPLAIN FORMAT=tree SELECT * FROM s1 INNER JOIN s2 ON s1.key1 = s2.key2 WHEREs1 .common_field = 'a ' \G

SHOW WARNINGS的使用

SHOW WARNINGS 可查看与查询执行计划相关的扩展信息。

show warnings \g

例如,如果原本的左连接因条件 s2.common_field IS NOT NULL 被优化为内连接,SHOW WARNINGS 的 Message 字段会反映这一变化。注意,Message 字段展示的信息并不是标准查询语句,而是帮助理解 MySQL 执行查询的参考信息。

四、高级诊断工具 🛠️

1️⃣ 查看SQL执行成本 : SHOW PROFILE

分析当前会话中SQL都做了什么、执行的资源消耗情况的工具,可用于sql调优的测量。默认情况下是关闭状态。

启用和查看
1. 检查状态:

show variables like 'profiling' #查看状态 默认OFF

2. 开启Profiiling

set profiling = 'ON' # 开启show profile

3. 查看执行情况:

SHOW PROFILES;  -- 查看所有执行的 SQL
SHOW PROFILE CPU, BLOCK IO FOR QUERY 12;  -- 查看特定 SQL 的详细信息

示例:
在这里插入图片描述
在这里插入图片描述

常用查询参数:

  • ALL: 显示所有的开销信息。
  • BLOCK IO: 显示块IO开销。
  • CONTEXT SWITCHES: 上下文切换开销。
  • CPU: 显示CPU开销信息。
  • IPC: 显示发送和接收开销信息。
  • MEMORY: 显示内存开销信息。
  • PAGE FAULTS: 显示页面错误开销信息。
  • SOURCE: 显示和Source_function,Source_file,Source_line相关的开销信息。
  • SWAPS: 显示交换次数开销信息。

日常开发注意事项:

  • converting HEAP to MyISA:查询结果过大时,数据会被写入磁盘。
  • Creating tmp table: 创建临时表。数据先拷贝到临时表,用完后再删除。
  • copying to tmp table on disk: 内存中临时表复制到磁盘可能影响性能。
  • locked:锁定问题,监测 SQL 执行中的锁定情况。。

注意
SHOW PROFILE 将被弃用,建议使用 information_schema 中的 profiling 数据表进行查看。

2️⃣. 分析优化器执行计划: OPTIMIZER_TRACE

OPTIMIZER_TRACE 是 MySQL 5.6 引入的功能,用于跟踪优化器的决策(如访问表的方法、开销计算等),并将结果记录到 INFORMATION_SCHEMA.OPTIMIZER_TRACE 表中。此功能默认关闭。
开启trace
要开启 TRACE 并设置格式为 JSON,同时限制最大内存使用:

SET optimizer_trace="enabled=on", end_markers_in_json=on;
set optimizer_trace_max_mem_size=1000000;

开启后,可分析如下语句:

  • SELECT
  • INSERT
  • REPLACE
  • UPDATE
  • DELETE
  • EXPLAIN
  • SET
  • DECLARE
  • CASE
  • IF
  • RETURN
  • CALL

示例
执行查询后,可以通过以下语句查看执行计划:

SELECT * FROM student WHERE id < 10;
SELECT * FROM INFORMATION_SCHEMA.optimizer_trace\G;

3️⃣ MySQL监控分析视图 - sys schema监控

MySQL 5.7.7 引入了 SYS schema,用于简化从 performance_schema 和 information_schema 中获取性能监控数据的复杂性,方便 DBA 快速定位问题。

  1. 主机相关:以 host_summary 开头,汇总 IO 延迟信息。
  2. InnoDB 相关:以 innodb 开头,汇总 InnoDB 缓冲区和事务锁等待信息。
示例:SELECT * FROM sys.innodb_lock_waits;
  1. I/O 相关:以 io 开头,汇总等待 I/O 和 I/O 使用情况。
示例:SELECT file, avg_read, avg_write FROM sys.io_global_by_file_by_bytes ORDER BY avg_read LIMIT 10;
  1. 内存使用情况:以 memory 开头,展示内存使用情况。
  2. 连接与会话信息:汇总会话相关信息。
  3. 表相关:以 schema_table 开头,展示表的统计信息。
示例:SELECT table_schema, table_name, SUM(io_read_requests + io_write_requests) FROM sys.schema_table_statistics GROUP BY table_schema, table_name ORDER BY io DESC;
  1. 索引信息:统计索引使用情况,包括冗余和未使用的索引。
示例:SELECT * FROM sys.schema_redundant_indexes;
  1. 语句相关:以 statement 开头,包含执行全表扫描、使用临时表等信息。
示例:SELECT db, exec_count, query FROM sys.statement_analysis ORDER BY exec_count DESC;
  1. 用户相关:以 user 开头,统计用户的文件 I/O 和执行语句信息。
    风险提示
    查询 SYS schema 可能消耗大量资源,严重时可能导致业务请求阻塞。建议在生产环境中避免频繁查询 SYS、performance_schema 或 information_schema。

五、调优口诀 📜

“一慢二看三分析,执行计划是核心;索引覆盖是王道,小表驱动效率高;监控日志常态化,锁表阻塞早排查”

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/984715.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法007——三数之和

力扣——三数之和&#xff08;点击跳转&#xff09; 做这道三数之和的题之前一定要先看我的上一篇笔记——两数之和&#xff08;点击跳转&#xff09;&#xff0c;只有把这个弄清楚这个 三数之和 才能明白 因为要去重&#xff0c;我们可以先将数组排序 我们先固定一个数&…

智慧城市智慧社区项目建设方案

一、项目背景 在全球化进程加速的今天&#xff0c;城市化问题日益凸显&#xff0c;传统的城市管理模式已难以满足现代社会对高效、智能化管理的需求。智慧城市和智慧社区的概念应运而生&#xff0c;其核心目标是通过信息技术手段&#xff0c;提升城市资源的利用效率&#xff0…

文件上传漏洞(upload靶场)

目录 Pass-01&#xff1a;前端绕过 方法一&#xff1a;浏览器禁用js 方法二:直接修改或删除js脚本 方法三&#xff1a;修改后缀绕过 Pass-02:服务器检测 Pess-03:黑名单绕过 Pass-04:.htaccess文件 Pass-05:windows特性和user.ini 方法一&#xff1a;php.自动解析为ph…

C++学习之QT综合项目二经典翻金币小游戏及打包

1.项目简介及创建 #include "chooselevelscene.h" #include <QMenuBar> #include <QMenu> #include <QPainter> #include "mypushbutton.h" #include <QTimer> #include <QDebug> #include <QLabel> #include…

前端项目中export和import的作用

之前写过代码&#xff0c;但是那个时候是使用jspdivcss写页面&#xff0c;jquery负责页面数据展示和数据请求。近期在学习前端&#xff0c;发现有export和import&#xff0c;想起了之前没用过&#xff0c;就研究搜索了一下&#xff0c;发现这个是在 ES6中添加的&#xff0c;难怪…

JVM 类加载原理之双亲委派机制(JDK8版本)

对 Java 程序的运行过程而言&#xff0c;类的加载依赖类加载器完成&#xff0c;而在 Java 默认的类加载器又分为启动类加载器、扩展类加载器和应用程序类加载器三种&#xff0c;但是一个类通常仅仅需要被加载一次即可&#xff0c;双亲委派机制即规定各个类该被何种类加载器加载…

【每日学点HarmonyOS Next知识】对话框去掉圆角、数组拼接、自定义对话框依附某个控件、平移动画、页面栈管理

1、 HarmonyOS CustomDialog怎么去掉左右和底部的透明以及圆角&#xff1f; CustomDialog怎么去掉左右和底部的透明以及圆角 设置customStyle为true即可开启使用自定义样式。设置borderRadius为0去掉圆角属性。 属性用法参考文档&#xff1a;https://developer.huawei.com/c…

坐落于杭州的电商代运营公司品融电商

坐落于杭州的电商代运营公司品融电商 在中国电商行业蓬勃发展的浪潮中&#xff0c;品融电商&#xff08;PINKROON&#xff09;作为一家扎根杭州的新锐品牌管理公司&#xff0c;凭借其独特的全域增长方法论和实战经验&#xff0c;迅速崛起为行业标杆。自2020年成立以来&#x…

【python爬虫】酷狗音乐爬取练习

注意&#xff1a;本次爬取的音乐仅有1分钟试听&#xff0c;仅作学习爬虫的原理&#xff0c;完整音乐需要自行下载客户端。 一、 初步分析 登陆酷狗音乐后随机选取一首歌&#xff0c;在请求里发现一段mp3文件&#xff0c;复制网址&#xff0c;确实是我们需要的url。 复制音频的…

Vue3 路由的历史记录 如何不允许浏览器前进后退 在函数中使用路由切换组件 路由的重定向

路由的历史记录模式 第一种push push会保留所有的切换记录&#xff0c;通过操作浏览器的前进后退&#xff0c;可以返回刚才浏览的页面 第二章replace replace不会保留路由的切换记录&#xff0c;不支持浏览器的前进后退 在函数中使用路由切换组件 页面挂载3秒后&#x…

【CSS3】金丹篇

目录 标准流概念元素类型及排列规则块级元素行内元素行内块元素 标准流的特点打破标准流 浮动基本使用清除浮动额外标签法单伪元素法双伪元素法&#xff08;推荐&#xff09;overflow 法 Flex 布局Flex 组成主轴对齐方式侧轴对齐方式修改主轴方向弹性盒子伸缩比弹性盒子换行行对…

解锁DeepSpeek-R1大模型微调:从训练到部署,打造定制化AI会话系统

目录 1. 前言 2.大模型微调概念简述 2.1. 按学习范式分类 2.2. 按参数更新范围分类 2.3. 大模型微调框架简介 3. DeepSpeek R1大模型微调实战 3.1.LLaMA-Factory基础环境安装 3.1大模型下载 3.2. 大模型训练 3.3. 大模型部署 3.4. 微调大模型融合基于SpirngBootVue2…

深入理解string:从模拟实现看本质

文章目录 摘要&#xff1a;一、引言二、string的模拟实现2.1 string类的定义 三、深拷贝和深赋值3.1 深浅拷贝构造函数3.2 深赋值运算符 四、总结五、附录5.1 完整代码6.2 测试用例 六、致谢 摘要&#xff1a; 本文将通过模拟实现一个简单的 String 类&#xff0c;深入探讨字符…

Unity组件TrailRenderer屏幕滑动拖尾

Unity组件TrailRenderer屏幕滑动拖尾 介绍制作总结 介绍 今天要做一个拖动效果&#xff0c;正好用到了TrailRenderer这个组件&#xff0c;正好分享一下 效果参考如下&#xff1a; 制作 1.创建空物体TrailObject添加组件TrailRenderer 下面的材质可以根据自己想要制作的效果去…

laravel中 添加公共/通用 方法/函数

一&#xff0c;现在app 下面创建Common目录&#xff0c;然后在创建Common.php 文件 二&#xff0c;修改composer.json文件 添加这个到autoload 中 "files": ["app/Common/Common.php"]"autoload": {"psr-4": {"App\\": &quo…

C#程序加密与解密Demo程序示例

目录 一、加密程序功能介绍 1、加密用途 2、功能 3、程序说明 4、加密过程 5、授权的注册文件保存方式 二、加密程序使用步骤 1、步骤一 ​编辑2、步骤二 3、步骤三 4、步骤四 三、核心代码说明 1、获取电脑CPU 信息 2、获取硬盘卷标号 3、机器码生成 3、 生成…

批量将 Excel 转换 PDF/Word/CSV以及图片等其它格式

Excel 格式转换是我们工作过程当中非常常见的一个需求&#xff0c;我们通常需要将 Excel 转换为其他各种各样的格式。比如将 Excel 转换为 PDF、比如说将 Excel 转换为 Word、再比如说将 Excel文档转换为图片等等。 这些操作对我们来讲都不难&#xff0c;因为我们通过 Office 都…

【报错】微信小程序预览报错”60001“

1.问题描述 我在微信开发者工具写小程序时&#xff0c;使用http://localhost:8080是可以请求成功的&#xff0c;数据全都可以无报错&#xff0c;但是点击【预览】&#xff0c;用手机扫描二维码浏览时&#xff0c;发现前端图片无返回且报错60001&#xff08;打开开发者模式查看日…

概念|RabbitMQ 消息生命周期 待消费的消息和待应答的消息有什么区别

目录 消息生命周期 一、消息创建与发布阶段 二、消息路由与存储阶段 三、消息存活与过期阶段 四、消息投递与消费阶段 五、消息生命周期终止 关键配置建议 待消费的消息和待应答的消息 一、待消费的消息&#xff08;Unconsumed Messages&#xff09; 二、待应答的消息…

电路原理(电容 集成电路NE555)

电容 1.特性&#xff1a;充放电&#xff0c;隔直流&#xff0c;通交流 2.电容是通过聚集正负电荷来存储电能的 3.电容充放电过程可等效为导通回路 4.多电容并联可以把容量叠加&#xff0c;但是多电容串联就不会&#xff0c;只会叠加电容的耐压值。 6.电容充放电时相当于通路&a…