检测服务器哪些语句慢,核心手段是打开数据库慢查询日志,配合实时抓取SQL和执行计划分析。 这是多数DBA和运维人员的共识,只要定位到那几条拖垮性能的语句,优化就有了明确靶点。
先把慢语句“捞”出来:慢查询日志怎么开
大多数后端服务卡顿,根子在数据库,服务器慢查询日志就是专门记录执行时间超过阈值的SQL语句的黑匣子,以最常见的MySQL为例,你不需要重启服务,在客户端直接执行以下命令就能打开:
SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 1; SET GLOBAL slow_query_log_file = '/var/log/mysql/mysql-slow.log';
- 第一行打开日志记录功能。
- 第二行设置阈值,执行时间超过1秒的语句会被记录,生产环境建议先设1秒,后续根据日志量调到0.5秒或更低。
- 第三行指定日志存放路径,确保MySQL进程对该目录有写权限。
如果你用的是MySQL 8.0或Percona分支,还能额外开启记录未使用索引的语句:SET GLOBAL log_queries_not_using_indexes = ON;,这能帮你揪出那些全表扫描却没慢到1秒的隐形炸弹。
数据放进去之后怎么查看?别直接cat整个日志文件,太大,用mysqldumpslow命令做聚合分析:
mysqldumpslow -t 10 -s at /var/log/mysql/mysql-slow.log
-s at表示按平均查询时间排序。-t 10只显示前10条最耗时的语句。
这条命令的输出会告诉你哪个SQL结构平均执行时间最长、累计执行多少次、总共消耗多少秒,比如输出里反复出现SELECT FROM orders WHERE status='P',那就说明这张表缺索引或数据分布失衡了。
不重启不落盘:生产环境实时抓取慢SQL
慢查询日志有个盲区只记录开启日志之后执行的语句,而且日志文件轮转不及时会占满磁盘,很多团队在排查线上问题时不想动全局配置,那就用实时抓取的办法。针对MySQL,SHOW FULL PROCESSLIST 是立竿见影的手段。 连上数据库执行这条命令,能看到当前所有正在执行的连接,其中Time列就是语句已经跑了多少秒,如果看到某个连接长时间停留在Sending data或Copying to tmp table状态,基本可以断定它就是拖垮业务的元凶。
直接看当前连接不够直观,可以每5秒采集一次快照,连续抓几次对比:
mysql -uroot -p -e "SHOW FULL PROCESSLIST" >> /tmp/slow_queries.txt
配合Linux的watch命令每5秒自动刷新:watch -n 5 "mysql -uroot -p -e 'SHOW FULL PROCESSLIST'",一旦发现某个Id反复出现且Time持续累积,立刻记录下它的Info,那就是需要优化的SQL语句,这种方式不需要改任何配置,适合临时排查、快速取证。
拿到慢语句之后:用执行计划定位瓶颈
捞到具体的慢语句不等于结束,你得知道它慢在哪一步。用EXPLAIN命令让数据库告诉你它的执行路径。 在慢语句前面加上EXPLAIN,
EXPLAIN SELECT FROM orders WHERE customer_id = 1024 ORDER BY created_at DESC;
返回结果里重点看三列:
type:全表扫描是ALL,走索引是ref或range,ALL说明没吃到索引。rows:预估扫描行数,从几万变成几百,优化效果立竿见影。Extra:如果出现Using filesort或Using temporary,意味着排序和分组操作在磁盘上完成,这比内存操作慢一个数量级。
行业共识认为,一条SQL的性能问题八成出在索引缺失或统计信息过期上。 结合慢查询日志里的高频语句,建立联合索引通常能解决大部分问题,例如上面那条语句,可以在(customer_id, created_at)上创建联合索引,既过滤客户又覆盖排序。
还有一类隐蔽的慢语句藏在ORM生成的SQL里,应用代码用findByCustomerIdOrderByCreatedAtDesc()这种方法名时,框架会自动拼出完整的SQL,你在MySQL通用日志里看到的一长串别名、子查询,往往就是ORM的“杰作”,排查时别忽略这一层,把框架的SQL日志级别调到DEBUG,直接归类打印出来的语句。
不同数据库和场景的排查差异
MySQL之外,其他主流数据库也有对应的检测手段,它们的核心逻辑一致但命令各异。
SQL Server怎么看
SQL Server没有独立的慢查询日志文件,用动态管理视图查:
SELECT TOP 10
text,
execution_count,
total_worker_time / 1000000 AS total_cpu_s,
total_elapsed_time / 1000000 AS total_duration_s
FROM sys.dm_exec_query_stats
CROSS APPLY sys.dm_exec_sql_text(sql_handle)
ORDER BY total_worker_time DESC;
这个查询直接返回累计消耗CPU时间最多的10条语句,执行一次,把total_duration_s除以execution_count得到单次平均耗时,重点处理那些平均耗时高且执行频繁的语句。
PostgreSQL的做法
PostgreSQL开启慢查询日志要在配置文件postgresql.conf里改:
log_min_duration_statement = 1000
设置成1000表示超过1秒的语句记录日志,改完重启数据库生效,日志里会写清楚语句全文和执行时间,配合pg_stat_statements扩展模块还能统计语句的调用次数和总耗时。
Redis和MongoDB
Redis的慢查询日志用命令查看:SLOWLOG GET 5,返回最近5条慢命令,MongoDB则用db.currentOp()抓取执行超过阈值的操作,它们的原理和关系型数据库类似,都是设置超时阈值加上定期检查。
常见语句慢的几类典型场景
根据大量生产事故复盘,慢语句集中出现在以下场景:
- 单表数据量超过千万级,索引失效导致扫描行数暴涨。
- 多表关联时关联字段类型不一致,索引被隐式转换干掉。
- 分页查询的
OFFSET过大,比如LIMIT 100000, 20,前10万行全部扫描。 - 查询列多于实际需要,
SELECT把不需要的大字段(如TEXT、BLOB)也读入内存。 - 同一SQL在高峰期并发激增,行锁等待时间计入执行时长。
一条慢语句从发现到解决的完整路径
拿一个真实案例走一遍流程:某天监控告警接口响应时间超过3秒,查看数据库慢查询日志发现SELECT FROM user_login_log WHERE user_id=12345 ORDER BY login_time DESC LIMIT 10平均执行2.8秒。
- 第二步用
EXPLAIN查看执行计划,发现type=ALL,表里有500万行,每次查询全表扫描。 - 第三步检查索引情况,
user_id字段虽然有索引,但排序字段login_time没有,数据库不得不把筛选结果放到临时表排序。 - 第四步创建联合索引:
ALTER TABLE user_login_log ADD INDEX idx_user_time (user_id, login_time);
- 第五步再次执行原语句,耗时降到15毫秒,慢查询日志里这条语句不再出现。
整个排查过程用时不到20分钟,绝大多数场景都可以按这条路径复制。
慢查询日志怎么设置生产配置对比
不同业务体量和数据库版本对慢查询日志的配置要求不同,下表列出常见方案作为参考:
| 配置项 | 小型业务(日活<10万) | 中型业务 | 大型业务 |
|---|---|---|---|
阈值long_query_time |
2秒 | 1秒 | 5秒 |
| 日志保留周期 | 7天 | 3天 | 1天 |
| 分析工具 | mysqldumpslow | pt-query-digest | 自研分析平台 |
| 是否开启未用索引日志 | 否 | 是 | 是 |
小业务量日志量小,保留时间长点没关系;大业务量日志增长快,分析工具必须自动化。 定期用工具导出Top 10耗时语句,建立每张表索引使用台账,慢语句基本逃不出监控视野。
检测服务器哪些语句慢:用户常见问题
怎么查看mysql慢查询日志是否已开启
执行SHOW VARIABLES LIKE 'slow_query_log';,结果Value为OFF即未开启,为ON则已开启,同时用SHOW VARIABLES LIKE 'long_query_time';查看阈值设置,MySQL默认10秒,生产环境建议调低到1秒或以下。
线上数据库无法重启,慢查询日志能立即生效吗
能,MySQL的SET GLOBAL命令修改慢查询相关参数不需要重启服务,慢查询日志开关和阈值都会即时生效。 但注意全局参数重启数据库后会恢复为配置文件中的值,若需永久生效得同步更新my.cnf,SQL Server不需要重启,杀到对应会话或等待批次结束即可。
慢日志里语句已经优化到毫秒级,但服务器还是慢怎么办
这种局面说明瓶颈已不在单条语句,转向服务器资源层面,在数据库所在服务器执行top看CPU和负载,用iostat看磁盘IO等待,用vmstat观察上下文切换。内网响应快慢还牵扯网络延迟和应用服务器线程池满没满,这类问题要多链路排查,单查SQL就找不到答案了。
数据库慢语句检测始终是个动态过程,业务增长、数据规模膨胀、索引失效都会让原本快速的语句慢慢变质,周期性用慢查询日志扫描、执行计划复核、索引重建这个循环,服务器性能才能持续跑在安全线上。最终判断标准就一条:语句执行时间是否符合业务对响应速度的预期。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/759976.html





