欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > MySQL性能调优实战手册:从慢查询到执行计划全解析

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

2025/3/11 11:01:09 来源:https://blog.csdn.net/qq_45438032/article/details/146159254  浏览:    关键词: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。

五、调优口诀 📜

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词