外观
MySQL 慢查询指标
核心慢查询指标
查询执行时间
指标定义
- query_time:查询执行的总时间(秒)
- avg_query_time:平均查询执行时间
- max_query_time:最大查询执行时间
- min_query_time:最小查询执行时间
- query_time_distribution:查询执行时间分布
收集方法
sql
-- 查看慢查询日志
SHOW VARIABLES LIKE 'slow_query_log%';
-- 设置慢查询阈值
SET GLOBAL long_query_time = 0.5;
-- 查看当前慢查询数量
SHOW GLOBAL STATUS LIKE 'Slow_queries';监控策略
- 设置合理的阈值
- 监控查询时间趋势
- 对超过阈值的查询进行告警
锁等待时间
指标定义
- lock_time:查询执行过程中的锁等待时间(秒)
- lock_time_ratio:锁等待时间占总执行时间的比例
- lock_wait_count:锁等待次数
- lock_wait_avg_time:平均锁等待时间
收集方法
sql
-- 查看InnoDB锁等待信息
SHOW GLOBAL STATUS LIKE 'Innodb_row_lock%';
-- 查看锁等待详情
SELECT * FROM performance_schema.data_locks;
SELECT * FROM performance_schema.data_lock_waits;监控策略
- 监控锁等待时间变化
- 分析锁等待原因
- 对长时间锁等待进行告警
扫描行数与返回行数
指标定义
- rows_examined:查询扫描的行数
- rows_sent:查询返回的行数
- rows_examined_ratio:扫描行数与返回行数的比例
- full_scan_count:全表扫描次数
收集方法
sql
-- 从慢查询日志中获取
-- 或从performance_schema中获取
SELECT * FROM performance_schema.events_statements_summary_by_digest
WHERE schema_name = 'your_database'
ORDER BY sum_rows_examined DESC;监控策略
- 监控扫描行数与返回行数的比例
- 识别全表扫描的查询
- 对扫描行数过多的查询进行优化
执行频率
指标定义
- query_count:查询执行次数
- query_frequency:查询执行频率(次/秒)
- top_queries:执行频率最高的查询
收集方法
sql
-- 从performance_schema中获取
SELECT DIGEST_TEXT, COUNT_STAR, SUM_TIMER_WAIT
FROM performance_schema.events_statements_summary_by_digest
WHERE schema_name = 'your_database'
ORDER BY COUNT_STAR DESC;监控策略
- 监控高频查询的性能
- 对高频慢查询进行重点优化
- 分析查询频率变化趋势
索引使用情况
指标定义
- index_used:是否使用索引
- index_name:使用的索引名称
- index_scan_count:索引扫描次数
- full_table_scan_count:全表扫描次数
收集方法
sql
-- 查看未使用索引的查询
SET GLOBAL log_queries_not_using_indexes = 'ON';
-- 从performance_schema中获取
SELECT DIGEST_TEXT, SUM_NO_INDEX_USED, SUM_ROWS_EXAMINED
FROM performance_schema.events_statements_summary_by_digest
WHERE schema_name = 'your_database'
AND SUM_NO_INDEX_USED > 0
ORDER BY SUM_NO_INDEX_USED DESC;监控策略
- 监控未使用索引的查询
- 分析索引使用效率
- 为高频全表扫描查询添加合适的索引
扩展慢查询指标
内存使用
指标定义
- memory_used:查询使用的内存量
- tmp_table_count:使用临时表的次数
- tmp_table_on_disk_count:使用磁盘临时表的次数
收集方法
sql
-- 查看临时表使用情况
SHOW GLOBAL STATUS LIKE 'Created_tmp%';
-- 从performance_schema中获取
SELECT DIGEST_TEXT, SUM_CREATED_TMP_TABLES, SUM_CREATED_TMP_DISK_TABLES
FROM performance_schema.events_statements_summary_by_digest
WHERE schema_name = 'your_database'
ORDER BY SUM_CREATED_TMP_DISK_TABLES DESC;监控策略
- 监控临时表使用情况
- 对使用磁盘临时表的查询进行优化
- 调整内存参数以减少临时表使用
网络传输
指标定义
- bytes_sent:查询返回的字节数
- bytes_received:查询接收的字节数
- network_latency:网络延迟
收集方法
sql
-- 查看网络传输情况
SHOW GLOBAL STATUS LIKE 'Bytes%';
-- 从performance_schema中获取
SELECT DIGEST_TEXT, SUM_BYTES_SENT, SUM_BYTES_RECEIVED
FROM performance_schema.events_statements_summary_by_digest
WHERE schema_name = 'your_database'
ORDER BY SUM_BYTES_SENT DESC;监控策略
- 监控大结果集查询
- 优化网络传输效率
- 考虑使用查询结果缓存
解析时间
指标定义
- parse_time:查询解析时间
- compile_time:查询编译时间
- execute_time:查询执行时间
收集方法
sql
-- 从performance_schema中获取
SELECT DIGEST_TEXT, SUM_PARSING_TIME, SUM_COMPILATION_TIME, SUM_EXECUTION_TIME
FROM performance_schema.events_statements_summary_by_digest
WHERE schema_name = 'your_database'
ORDER BY SUM_PARSING_TIME + SUM_COMPILATION_TIME DESC;监控策略
- 监控查询解析和编译时间
- 优化复杂查询的解析效率
- 考虑使用预处理语句
子查询性能
指标定义
- subquery_count:子查询数量
- subquery_execution_time:子查询执行时间
- correlated_subquery_count:相关子查询数量
收集方法
sql
-- 分析查询执行计划
EXPLAIN SELECT * FROM table WHERE id IN (SELECT id FROM sub_table);
-- 从performance_schema中获取复杂查询
SELECT DIGEST_TEXT, SUM_TIMER_WAIT
FROM performance_schema.events_statements_summary_by_digest
WHERE schema_name = 'your_database'
AND DIGEST_TEXT LIKE '%SELECT%(%SELECT%'%'
ORDER BY SUM_TIMER_WAIT DESC;监控策略
- 监控子查询性能
- 优化相关子查询
- 考虑使用JOIN替代子查询
指标收集方法
慢查询日志
配置
ini
[mysqld]
# 启用慢查询日志
slow_query_log = 1
# 设置慢查询阈值
long_query_time = 0.5
# 设置慢查询日志文件路径
slow_query_log_file = /var/log/mysql/mysql-slow.log
# 记录未使用索引的查询
log_queries_not_using_indexes = 1
# 记录管理语句
log_slow_admin_statements = 1分析工具
- mysqldumpslow:MySQL自带工具
- pt-query-digest:Percona Toolkit工具
- MySQL Enterprise Monitor:企业级监控工具
Performance Schema
启用
sql
-- 启用Performance Schema
SET GLOBAL performance_schema = 'ON';
-- 验证启用状态
SHOW VARIABLES LIKE 'performance_schema';相关表
- events_statements_summary_by_digest:按语句摘要汇总的语句事件
- events_statements_history:语句事件历史
- events_statements_history_long:长语句事件历史
查询示例
sql
-- 查看执行时间最长的查询
SELECT DIGEST_TEXT, SUM_TIMER_WAIT/1000000000 as sum_time_sec,
AVG_TIMER_WAIT/1000000000 as avg_time_sec,
COUNT_STAR as exec_count
FROM performance_schema.events_statements_summary_by_digest
WHERE schema_name = 'your_database'
ORDER BY sum_time_sec DESC
LIMIT 10;Sys Schema
简介
- 基于Performance Schema的视图集合
- 提供更友好的查询接口
- 简化性能数据收集
相关视图
- sys.statements_with_runtimes_in_95th_percentile:95百分位运行时间的语句
- sys.statements_with_full_table_scans:使用全表扫描的语句
- sys.statements_with_temp_tables:使用临时表的语句
查询示例
sql
-- 查看慢查询
SELECT * FROM sys.statements_with_runtimes_in_95th_percentile
WHERE schema_name = 'your_database'
ORDER BY avg_execution_time DESC;
-- 查看使用全表扫描的查询
SELECT * FROM sys.statements_with_full_table_scans
WHERE schema_name = 'your_database'
ORDER BY rows_examined DESC;第三方监控工具
Prometheus + MySQL Exporter
- 开源监控解决方案
- 支持MySQL指标收集
- 提供时序数据存储
- 与Grafana集成实现可视化
MySQL Enterprise Monitor
- 企业级监控工具
- 提供预定义的慢查询监控面板
- 支持自动告警
- 集成到MySQL Enterprise Edition
Zabbix
- 综合监控系统
- 支持MySQL监控模板
- 可自定义慢查询监控项
- 提供丰富的告警机制
监控策略
指标阈值设置
基于业务需求
- OLTP系统:阈值较低(如0.1秒)
- OLAP系统:阈值较高(如5秒)
- 混合系统:根据查询类型设置不同阈值
基于历史数据
- 分析历史查询执行时间分布
- 建立性能基线
- 根据基线设置合理阈值
动态调整
- 高峰期和低谷期设置不同阈值
- 根据系统负载动态调整
- 定期评估和更新阈值
监控频率
实时监控
- 对关键业务查询进行实时监控
- 配置实时告警
- 快速响应性能问题
定期分析
- 每日慢查询分析
- 每周性能报告
- 每月趋势分析
长期趋势
- 建立长期性能趋势数据
- 预测性能变化
- 制定容量规划
告警策略
告警级别
- 严重:查询执行时间超过阈值5倍
- 警告:查询执行时间超过阈值
- 提示:查询执行时间接近阈值
告警方式
- 邮件:详细的性能报告
- 短信:紧急告警
- 即时通讯:实时通知
- 监控平台:集中展示
告警抑制
- 避免告警风暴
- 实现告警聚合
- 工作时间和非工作时间采用不同策略
指标分析方法
单指标分析
分析步骤
- 收集指标数据
- 与历史数据对比
- 与基线对比
- 识别异常值
- 分析异常原因
示例
sql
-- 查看慢查询数量趋势
SELECT
DATE_FORMAT(event_time, '%Y-%m-%d %H:00:00') as time_slot,
COUNT(*) as slow_query_count
FROM mysql.slow_log
WHERE start_time >= NOW() - INTERVAL 24 HOUR
GROUP BY time_slot
ORDER BY time_slot;多指标关联分析
分析步骤
- 选择相关指标
- 建立关联关系
- 分析指标间的相关性
- 识别综合性能问题
示例
sql
-- 分析扫描行数与执行时间的关系
SELECT
DIGEST_TEXT,
SUM_TIMER_WAIT/1000000000 as sum_time_sec,
SUM_ROWS_EXAMINED,
SUM_ROWS_SENT,
SUM_ROWS_EXAMINED / SUM_ROWS_SENT as scan_to_send_ratio
FROM performance_schema.events_statements_summary_by_digest
WHERE schema_name = 'your_database'
AND SUM_ROWS_SENT > 0
ORDER BY sum_time_sec DESC
LIMIT 10;趋势分析
分析步骤
- 收集一段时间的指标数据
- 绘制趋势图表
- 识别趋势变化点
- 分析变化原因
示例
sql
-- 分析慢查询数量趋势
SELECT
DATE_FORMAT(event_time, '%Y-%m-%d') as date,
COUNT(*) as slow_query_count
FROM mysql.slow_log
WHERE start_time >= NOW() - INTERVAL 30 DAY
GROUP BY date
ORDER BY date;基准对比分析
分析步骤
- 建立性能基线
- 定期与基线对比
- 分析偏差原因
- 调整基线
示例
sql
-- 建立基线
CREATE TABLE performance_baseline (
metric_name VARCHAR(100),
baseline_value FLOAT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 插入基线数据
INSERT INTO performance_baseline (metric_name, baseline_value)
VALUES ('avg_query_time', 0.1),
('max_query_time', 2.0),
('slow_query_count', 100);
-- 与基线对比
SELECT
'avg_query_time' as metric_name,
AVG(query_time) as current_value,
(SELECT baseline_value FROM performance_baseline WHERE metric_name = 'avg_query_time') as baseline_value,
(AVG(query_time) / (SELECT baseline_value FROM performance_baseline WHERE metric_name = 'avg_query_time') - 1) * 100 as deviation_percent
FROM mysql.slow_log
WHERE start_time >= NOW() - INTERVAL 1 HOUR;优化建议
基于执行时间的优化
优化策略
- 添加索引:为WHERE条件和JOIN条件添加合适的索引
- 优化SQL:重写复杂查询,分解大查询
- 调整参数:优化MySQL配置参数
- 硬件升级:增加CPU、内存、SSD等硬件资源
示例
sql
-- 原查询(无索引)
SELECT * FROM users WHERE last_name = 'Smith';
-- 优化后(添加索引)
CREATE INDEX idx_last_name ON users(last_name);
SELECT * FROM users WHERE last_name = 'Smith';基于锁等待的优化
优化策略
- 减少事务范围:缩短事务持有锁的时间
- 优化锁粒度:使用行级锁替代表级锁
- 合理的索引:减少锁冲突
- 并发控制:使用乐观锁或悲观锁
示例
sql
-- 原查询(长事务)
START TRANSACTION;
UPDATE users SET balance = balance - 100 WHERE id = 1;
-- 其他操作...
COMMIT;
-- 优化后(短事务)
START TRANSACTION;
UPDATE users SET balance = balance - 100 WHERE id = 1;
COMMIT;
-- 其他操作...基于扫描行数的优化
优化策略
- 添加索引:减少全表扫描
- 优化WHERE条件:使用索引友好的查询条件
- 限制结果集:使用LIMIT限制返回行数
- **避免SELECT ***:只选择需要的列
示例
sql
-- 原查询(全表扫描)
SELECT * FROM orders WHERE order_date > '2023-01-01';
-- 优化后(添加索引)
CREATE INDEX idx_order_date ON orders(order_date);
SELECT order_id, customer_id, total FROM orders WHERE order_date > '2023-01-01' LIMIT 100;基于执行频率的优化
优化策略
- 缓存结果:使用查询缓存或应用层缓存
- 批量操作:将多个单条操作合并为批量操作
- 预处理语句:使用预处理语句减少解析开销
- 代码优化:减少应用程序中的重复查询
示例
sql
-- 原查询(多次执行)
for user_id in user_ids:
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
-- 优化后(批量查询)
cursor.execute("SELECT * FROM users WHERE id IN (%s)", (','.join(map(str, user_ids)),))基于索引使用的优化
优化策略
- 添加合适的索引:为常用查询添加索引
- 优化索引结构:使用复合索引,优化索引顺序
- 避免索引失效:避免在WHERE条件中使用函数
- 定期维护索引:重建碎片化索引
示例
sql
-- 原查询(索引失效)
SELECT * FROM users WHERE YEAR(created_at) = 2023;
-- 优化后(使用索引)
CREATE INDEX idx_created_at ON users(created_at);
SELECT * FROM users WHERE created_at BETWEEN '2023-01-01' AND '2023-12-31';最佳实践
指标收集最佳实践
全面性
- 收集多维度的慢查询指标
- 覆盖所有类型的SQL操作
- 包括执行计划信息
及时性
- 实时收集关键指标
- 定期汇总分析
- 及时发现性能问题
准确性
- 使用精确的时间戳
- 避免指标数据丢失
- 确保数据一致性
指标监控最佳实践
可视化
- 使用图表展示性能趋势
- 建立监控仪表板
- 突出显示异常指标
自动化
- 自动化指标收集
- 自动化告警
- 自动化分析报告
集成性
- 与其他监控系统集成
- 与CI/CD流程集成
- 与日志分析系统集成
指标分析最佳实践
上下文分析
- 结合系统负载分析
- 结合业务场景分析
- 结合代码变更分析
根因分析
- 深入分析性能问题的根本原因
- 避免只处理表面现象
- 提出系统性的解决方案
持续改进
- 建立性能改进闭环
- 跟踪优化措施的效果
- 持续调整优化策略
常见问题(FAQ)
Q1: 如何设置合理的慢查询阈值?
A1: 设置慢查询阈值应考虑:
- 业务需求:不同业务对响应时间的要求不同
- 系统配置:硬件性能影响查询执行时间
- 查询类型:OLTP和OLAP查询设置不同阈值
- 历史数据:分析历史查询执行时间分布
- 建议:从小值开始(如0.1秒),根据实际情况调整
Q2: 慢查询指标监控会影响MySQL性能吗?
A2: 监控慢查询指标会对MySQL性能产生一定影响:
- 慢查询日志:额外的I/O操作
- Performance Schema:额外的内存和CPU开销
- 影响程度:取决于监控的详细程度和频率
- 建议:
- 合理设置慢查询阈值
- 对Performance Schema进行适当配置
- 生产环境中选择合适的监控策略
Q3: 如何处理大量的慢查询数据?
A3: 处理大量慢查询数据的方法:
- 数据聚合:使用工具对慢查询数据进行聚合分析
- 数据轮转:定期轮转慢查询日志
- 数据归档:将历史数据归档到外部存储
- 智能分析:使用机器学习等技术识别重要的慢查询
- 重点关注:优先分析执行时间长、执行频率高的查询
Q4: 如何区分慢查询和正常查询的边界?
A4: 区分方法:
- 基于业务SLA:根据服务级别协议确定
- 基于历史数据:分析查询执行时间分布
- 基于资源使用:考虑CPU、I/O等资源消耗
- 基于用户体验:考虑用户感知的响应时间
- 动态调整:根据系统负载和业务情况动态调整阈值
Q5: 如何将慢查询指标与其他监控指标关联分析?
A5: 关联分析方法:
- 系统指标:结合CPU、内存、磁盘I/O等指标
- MySQL指标:结合连接数、缓冲区使用等指标
- 应用指标:结合应用响应时间、错误率等指标
- 业务指标:结合交易量、用户数等指标
- 工具集成:使用Prometheus、Grafana等工具实现多指标关联展示
