MySQL查找SQL耗时瓶颈 SHOW profiles

本文介绍如何使用MySQL的profiling功能来分析SQL语句的执行效率。通过开启profiling功能并执行特定的SQL语句,可以获取详细的性能报告,进而帮助开发者定位和优化数据库性能瓶颈。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、首先查看是否开启profiling功能
SHOW VARIABLES LIKE '%pro%';

或者

SELECT @@profiling;


2、开启profiling

SET profiling=1;

3、执行sql语句

例如:

SELECT 
  table_schema AS 'Db Name',
  ROUND( SUM( data_length + index_length ) / 1024 / 1024, 3 ) AS 'Db Size (MB)',
  ROUND( SUM( data_free ) / 1024 / 1024, 3 ) AS 'Free Space (MB)'
FROM information_schema.tables
GROUP BY table_schema ;

4、查看结果

SHOW profiles;
SHOW profile ALL FOR QUERY 94;

94是查询ID号。

SHOW profiles语法:

SHOW PROFILE [type [, type] … ]
    [FOR QUERY n]
    [LIMIT row_count [OFFSET offset]]

type:
    ALL
  | BLOCK IO
  | CONTEXT SWITCHES
  | CPU
  | IPC
  | MEMORY
  | PAGE FAULTS
  | SOURCE
  | SWAPS



 

<think>我们正在分析MySQL查询性能问题,特别是当`show profile`显示`executing`状态耗时过长的情况。根据用户提供的引用和之前的历史,我们需要系统地解释原因并提供优化方案。 关键点: 1. `executing`状态表示SQL在服务器线程中实际执行的时间,包括数据处理、计算等核心操作。 2. 时间过长通常由全表扫描、复杂计算、内存不足或锁竞争引起。 我们将按照以下结构组织回答: 一、`executing`状态过高的常见原因 二、诊断步骤(使用`show profile`和其他工具) 三、优化策略 四、高级技巧 同时,我们将引用用户提供的参考内容,并在适当位置标注引用。 注意:在数学表达式中,使用$...$格式,例如:$O(n)$,独立公式使用$$...$$。 开始回答:</think>### MySQL `executing` 状态耗时过长:原因分析与优化指南 当 `SHOW PROFILE` 显示 `executing` 阶段耗时过高时,表明 SQL 的核心执行环节存在瓶颈。以下是系统化的诊断与优化流程: --- #### 一、核心原因分析 1. **全表扫描与索引失效** - **现象**:`EXPLAIN` 显示 `type=ALL` 或 `key=NULL` - **数学表达**: 若表行数为 $N$,全表扫描时间复杂度为 $O(N)$,而索引扫描为 $O(\log N)$ - **典型场景**: ```sql SELECT * FROM orders WHERE YEAR(order_date)=2023; -- 函数导致索引失效[^4] ``` 2. **复杂计算与聚合** - 高开销操作:`GROUP BY`、`DISTINCT`、窗口函数 - **资源消耗公式**: $$ \text{内存需求} = \text{分组列基数} \times \text{行大小} $$ 超出 `sort_buffer_size` 时触发磁盘临时表(性能下降 10-100 倍)[^3] 3. **锁竞争与资源等待** - 行锁等待(`SHOW ENGINE INNODB STATUS` 查看 `TRANSACTIONS`) - 磁盘 I/O 瓶颈(`iostat` 显示 `%util > 70%`) 4. **执行计划错误** - 统计信息过期导致优化器选择低效计划 - 子查询未优化(如 `DEPENDENT SUBQUERY`) --- #### 二、诊断工具链(逐步操作) ```sql -- 1. 开启性能分析 SET SESSION profiling = 1; -- 会话级启用[^3] -- 2. 执行目标SQL SELECT id%10 FROM emp GROUP BY id%10 LIMIT 150000; -- 示例高开销查询[^4] -- 3. 查看概要耗时 SHOW PROFILES; -- 获取Query_ID[^1] -- 4. 精确定位瓶颈(替换N为Query_ID) SHOW PROFILE CPU, BLOCK IO, CONTEXT SWITCHES FOR QUERY N; ``` **输出关键指标**: | 状态 | 诊断指向 | |-------------------|-----------------------------| | `executing` + 高CPU | 计算密集型操作(如聚合函数) | | `executing` + 高IO | 全表扫描/临时表写入磁盘 | | `Sending data` 长 | 结果集过大或网络传输瓶颈 | --- #### 三、优化策略与实战案例 1. **索引优化** **问题SQL**: ```sql SELECT * FROM logs WHERE status IN (1,7) AND source IN (11,12,13); -- 全表扫描[^5] ``` **优化方案**: ```sql -- 添加覆盖索引 ALTER TABLE logs ADD INDEX idx_status_source (status, source); -- 改写查询(避免IN条件索引失效) SELECT * FROM logs WHERE (status=1 AND source=11) OR (status=1 AND source=12) ...; -- 拆分为UNION ALL更高效 ``` 2. **内存与计算优化** ```sql -- 增大排序缓冲区(默认256KB) SET SESSION sort_buffer_size = 8*1024*1024; -- 8MB -- 预计算复杂聚合(物化视图) CREATE TABLE daily_sales_summary AS SELECT date, SUM(amount) FROM sales GROUP BY date; -- 避免实时计算[^2] ``` 3. **执行计划干预** ```sql -- 强制使用索引 SELECT * FROM orders FORCE INDEX(idx_order_date) WHERE order_date BETWEEN '2023-08-01' AND '2023-08-31'; -- 更新统计信息 ANALYZE TABLE orders; ``` --- #### 四、高级技巧 1. **批处理替代循环** ```sql -- 低效:N+1查询 UPDATE users SET last_login=NOW() WHERE id IN (SELECT user_id FROM logs); -- 高效:单次JOIN UPDATE users u JOIN logs l ON u.id=l.user_id SET u.last_login=NOW(); ``` 2. **避免隐式类型转换** ```sql -- 字符串字段按数字查询(索引失效) SELECT * FROM products WHERE product_id = 100; -- product_id VARCHAR(20) -- 优化:显式转换 SELECT * FROM products WHERE product_id = '100'; ``` > **关键指标验证**:优化后检查 `Handler_read_rnd_next`(全表扫描行数)是否显著下降: > ```sql > FLUSH STATUS; > 执行SQL; > SHOW SESSION STATUS LIKE 'Handler%'; -- 目标:Handler_read_rnd_next趋近0 > ``` --- ### 相关问题 1. 如何通过 `EXPLAIN ANALYZE` 在 MySQL 8 中获取更精确的执行计划耗时? 2. 当 `SHOW PROFILE` 显示 `Creating sort index` 耗时过高时,有哪些内存参数需要调整? 3. InnoDB 缓冲池命中率如何影响 `executing` 阶段的磁盘 I/O? 4. MySQL 8 的直方图统计信息如何优化 `WHERE status IN (1,7)` 这类查询? [^1]: 通过 `SHOW PROFILES` 可查看 SQL 执行时间分布 [^2]: `SHOW PROFILES` 是识别性能瓶颈的关键工具 [^3]: 需动态开启 profiling 功能进行会话级分析 [^4]: 复杂聚合操作易导致 `executing` 阶段耗时激增 [^5]: 业务逻辑错误的 SQL 会导致无效全表扫描
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值