适用版本:MySQL 5.7 / 8.0
今天聊一聊sql优化的问题,怎么找到那些慢SQL。
一、什么是慢 SQL
慢 SQL 是指执行时间超过预设阈值的 SQL 语句。在 MySQL 中,这个阈值由参数 long_query_time 控制,默认值为 10 秒,实际生产环境中通常设置为 1~2 秒。
慢 SQL 是数据库性能问题最常见的根源,主要表现为:
页面响应缓慢,接口超时数据库 CPU 飙高,连接数堆积锁等待,导致其他业务也受影响二、开启慢查询日志
要找到慢 SQL,首先需要开启 MySQL 的慢查询日志功能。
2.1 查看当前状态
SHOW VARIABLES LIKE 'slow_query%'; SHOW VARIABLES LIKE 'long_query_time';
2.2 临时开启(重启后失效)
-- 开启慢查询日志 SET GLOBAL slow_query_log = 'ON'; -- 设置阈值:超过 2 秒算慢 SQL SET GLOBAL long_query_time = 2; -- 设置日志输出到表(推荐,方便直接查询) SET GLOBAL log_output = 'TABLE';
2.3 永久生效(修改配置文件)
编辑 MySQL 配置文件 my.cnf(Linux)或 my.ini(Windows):
[mysqld] slow_query_log = 1 long_query_time = 2 log_output = TABLE log_queries_not_using_indexes = 1 # 同时记录未使用索引的 SQL
建议:log_queries_not_using_indexes = 1 非常有用,即使执行很快但没走索引的 SQL 也会被记录,可以提前发现潜在隐患。
三、方法一:查询 slow_log 表
当 log_output = TABLE 时,慢 SQL 会写入 mysql.slow_log 表,可以直接用 SQL 查询。
3.1 查询最近的慢 SQL
SELECT start_time, ROUND(TIME_TO_SEC(query_time), 3) AS 执行秒数, ROUND(TIME_TO_SEC(lock_time), 3) AS 锁等待秒数, rows_examined AS 扫描行数, rows_sent AS 返回行数, db AS 数据库, sql_text AS SQL内容 FROM mysql.slow_log ORDER BY query_time DESC LIMIT 20;
3.2 按数据库筛选
SELECT * FROM mysql.slow_log WHERE db = 'your_database' ORDER BY query_time DESC LIMIT 20;
四、方法二:performance_schema 分析
performance_schema 是 MySQL 内置的性能数据采集框架,能统计所有 SQL 的累计执行情况,找出高频且耗时的 SQL。
4.1 查询最耗时的 TOP 10 SQL
SELECT DIGEST_TEXT AS SQL摘要, COUNT_STAR AS 执行次数, ROUND(AVG_TIMER_WAIT / 1000000000000, 3) AS 平均耗时秒, ROUND(MAX_TIMER_WAIT / 1000000000000, 3) AS 最大耗时秒, ROUND(SUM_TIMER_WAIT / 1000000000000, 3) AS 总耗时秒, SUM_ROWS_EXAMINED AS 总扫描行数 FROM performance_schema.events_statements_summary_by_digest ORDER BY SUM_TIMER_WAIT DESC LIMIT 10;
4.2 通过 sys schema 更简便地查询
sys schema 是对 performance_schema 的封装,SQL 更简洁易读:
-- 查询最耗时的 SQL(按总耗时排序) SELECT * FROM sys.statement_analysis ORDER BY total_latency DESC LIMIT 10; -- 查询全表扫描最多的 SQL SELECT * FROM sys.statements_with_full_table_scans ORDER BY no_index_used_count DESC LIMIT 10;
五、方法三:工具客户端分析
5.1 MySQL Workbench(推荐)
连接数据库后,在左侧导航找到 Performance 菜单:
Performance → Dashboard:实时监控面板,查看 QPS、连接数、缓冲池等Performance → Statement Analysis:列出所有 SQL 及其平均耗时、执行次数Performance → Query Statistics:按类型统计 SELECT/INSERT/UPDATE 的耗时占比5.2 DBeaver
执行 SQL 后,底部结果面板直接显示执行时间Window → Query Manager:查看历史 SQL 及每条的耗时选中 SQL →Ctrl+Shift+E:图形化执行计划
5.3 Percona PMM(生产环境推荐)
PMM(Percona Monitoring and Management)是专业的 MySQL 监控平台,适合生产环境:
Query Analytics 面板:实时展示所有 SQL 的执行频率和耗时支持按时间段过滤,定位某次性能抖动期间的慢 SQL可下钻到单条 SQL 查看执行计划和历史趋势六、找到慢 SQL 后如何分析
找到慢 SQL 只是第一步,接下来需要通过执行计划(EXPLAIN)分析慢的原因。
6.1 使用 EXPLAIN 分析
EXPLAIN SELECT * FROM orders WHERE user_id = 123 AND status = 1; -- MySQL 8.0+ 支持更详细的 EXPLAIN ANALYZE EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 123 AND status = 1;
6.2 关键字段解读
6.3 常见慢 SQL 原因
未建索引,或索引建了但没有命中(索引失效)SQL 写法导致索引失效,例如对索引列使用函数、隐式类型转换SELECT * 拉取了不必要的列,返回数据量过大JOIN 关联字段未建索引,产生笛卡尔积数据量大但没有分页,一次查询百万行数据
七、排查流程总结
八、常用命令速查
-- 查看慢查询配置 SHOW VARIABLES LIKE 'slow%'; -- 开启慢查询日志 SET GLOBAL slow_query_log = 'ON'; -- 设置慢查询阈值(秒) SET GLOBAL long_query_time = 2; -- 查询慢 SQL 列表 SELECT * FROM mysql.slow_log ORDER BY query_time DESC LIMIT 20; -- 查 TOP 10 耗时 SQL SELECT * FROM sys.statement_analysis LIMIT 10; -- 查全表扫描的 SQL SELECT * FROM sys.statements_with_full_table_scans LIMIT 10; -- 分析执行计划 EXPLAIN SELECT ...; -- 详细执行计划(MySQL 8.0+) EXPLAIN ANALYZE SELECT ...; -- 清空慢日志表 TRUNCATE TABLE mysql.slow_log;
小结:慢 SQL 排查的核心思路是「先发现、再定位、后优化」。建议在测试和生产环境都长期开启慢查询日志,并定期检查 sys.statement_analysis,做到防患于未然。
到此这篇关于SQL性能优化之慢SQL查询方法与排查的文章就介绍到这了,
