DBAtlas · 数据库运维图谱

慢查询:深入诊断

某个查询或整个系统很慢。逐步缩小范围:在每个节点执行检查,并根据结果选择分支。最终得到根本原因 + 修复方案。

什么慢?

是一个或少数几个特定查询慢,还是整个系统慢?据此将排查分为两条路径之一:“以查询为中心”或“以资源/瓶颈为中心”。

  • 一个或少数几个特定查询慢
  • 整个系统都慢

查询此刻正在运行吗?

是此刻正在运行/卡住的查询,还是“一直都慢”的查询?查看活动会话。

SELECT sid, serial#, sql_id, last_call_et AS running_sec, event, blocking_session
FROM v$session WHERE status='ACTIVE' AND type='USER' ORDER BY last_call_et DESC;
  • 此刻正在运行/卡住
  • 一直都慢;我想看它的执行计划

查询是否在等待什么?

如果它处于活动状态却没有进展,很可能是在等待。blocking_session / wait_event 是否有值?

SELECT sid, blocking_session, event, seconds_in_wait
FROM v$session WHERE sid=&target_sid;
  • 被另一个会话阻塞
  • 在等待资源(IO / 日志 / latch)
  • 没有等待;正在大量消耗 CPU

哪种等待占主导?

占主导的等待事件说明了瓶颈的类型。

SELECT event, total_waits, time_waited FROM v$session_event WHERE sid=&target_sid ORDER BY time_waited DESC FETCH FIRST 5 ROWS ONLY;
  • IO 等待(db file read / PAGEIOLATCH)
  • 日志/提交等待(log file sync / WRITELOG)
  • 锁/队列(enq: TX / LCK)

获取执行计划(EXPLAIN)

取出执行计划。是否有全表扫描、意外的连接顺序,或估算行数与实际行数之间的差距?

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id', NULL, 'ALLSTATS LAST'));
  • 全表扫描/缺少索引
  • 昨天还很快;执行计划突然变了
  • 处理的行太多 / N+1
  • 执行计划看起来不错但仍然慢

统计信息是否最新?

估算行数与实际行数(E-rows 与 A-rows)差距很大,是统计信息过时的迹象。

SELECT table_name, num_rows, last_analyzed FROM dba_tables WHERE table_name='&TABLE_NAME';
  • 统计信息过时/陈旧
  • 统计信息是最新的但仍然慢

系统级:瓶颈在哪里?

如果是所有操作都慢而不是单个查询,就要查找资源瓶颈:CPU、IO、内存,还是大范围阻塞?

SELECT metric_name, value FROM v$sysmetric WHERE metric_name IN ('Host CPU Utilization (%)','Average Active Sessions') AND intsize_csec=(SELECT MAX(intsize_csec) FROM v$sysmetric);
  • CPU 接近 100%
  • IO 等待高
  • 内存压力/缓存命中率低
  • 大量阻塞

根本原因:阻塞

查询在等待另一个会话持有的锁。找到链条最前端的会话(根阻塞者)并加以处理。

根本原因:IO 瓶颈

查询从磁盘读取大量数据。通常源于全表扫描(缺少索引)或内存(buffer cache)不足。

根本原因:提交/日志瓶颈

若 'log file sync' / 'WRITELOG' 占主导,说明提交在等待 redo/WAL 写入。

根本原因:缺少索引

执行计划在做全表扫描。在过滤/连接列上建立合适的索引会大幅提速。

根本原因:执行计划回归

查询昨天还快,今天却不快了;执行计划变了。通常是统计信息过时或参数变更所致。

根本原因:查询设计

执行计划合理,但查询本身做了太多工作(行太多、N+1、不必要的连接)。

根本原因:统计信息过时

由于统计信息不是最新的,优化器估算错误。

深入分析

若执行计划和统计信息都没问题但仍然慢,就要深入挖掘。

根本原因:CPU 瓶颈

整个系统受 CPU 限制。通常是少数几个执行计划糟糕的查询在大量消耗 CPU。

根本原因:内存压力

缓存命中率低和/或发生 swap:内存不足或分配不当。

在 DBAtlas 中打开 →