ITPub博客

首页 > 数据库 > Oracle > 第62期 Oracle通过DBA_HIST_SQLSTAT 追踪SQL历史性能问题

第62期 Oracle通过DBA_HIST_SQLSTAT 追踪SQL历史性能问题

原创 Oracle 作者:pxbibm 时间:2026-05-14 17:05:49 0 删除 编辑

DBA_HIST_SQLSTAT 是 Oracle AWR(自动负载仓库)中记录 SQL 执行统计历史的核心视图,保存了被采样的 SQL 在各快照区间的性能数据。所有指标都分 _TOTAL(实例启动以来累计) 和 _DELTA(快照区间增量) 两类。配合 AWR 快照,精准定位慢 SQL、分析性能趋势、溯源性能抖动、做 SQL 优化复盘,生产 DBA 日常高频用法。

下面介绍一下这个 DBA_HIST_SQLSTAT试图所有列的含义:

一、主键 / 标识列(定位唯一记录)

表格
列名 类型 说明
SNAP_ID NUMBER NOT NULL 快照 ID(关联 DBA_HIST_SNAPSHOT)
DBID NUMBER NOT NULL 数据库 ID
INSTANCE_NUMBER NUMBER NOT NULL 实例号(RAC)
SQL_ID VARCHAR2(13) NOT NULL SQL 唯一 ID
PLAN_HASH_VALUE NUMBER NOT NULL 执行计划哈希值(计划不变则值不变)

二、执行次数类

表格


列名 说明
EXECUTIONS_TOTAL 累计执行次数
EXECUTIONS_DELTA 快照内执行次数(最常用)
PX_SERVERS_EXECS_TOTAL 并行执行累计次数
PX_SERVERS_EXECS_DELTA 快照内并行执行次数
END_OF_FETCH_COUNT_DELTA 完整执行完成(fetch 到末尾)的次数


三、时间类(单位:微秒)

表格
列名 说明
ELAPSED_TIME_DELTA 总耗时(解析 + 执行 + fetch)
CPU_TIME_DELTA CPU 耗时
IOWAIT_DELTA 用户 I/O 等待时间
APWAIT_DELTA 应用等待(行锁、事务等)
CCWAIT_DELTA 并发等待(latch/lock)
CLWAIT_DELTA RAC 集群等待
PLSEXEC_TIME_DELTA PL/SQL 执行时间

四、I/O 与缓存类

表格
列名 说明
BUFFER_GETS_DELTA 逻辑读(内存读,性能核心)
DISK_READS_DELTA 物理读(磁盘读)
DIRECT_WRITES_DELTA 直接路径写(临时表、并行加载)
PHYSICAL_READ_BYTES_DELTA 物理读字节数
PHYSICAL_WRITE_BYTES_DELTA 物理写字节数
ROWS_PROCESSED_DELTA 返回总行数

五、解析与内存类

表格
列名 说明
PARSE_CALLS_DELTA 解析调用次数(硬解析 + 软解析)
LOADS_DELTA SQL 重载(硬解析)次数
INVALIDATIONS_DELTA 游标失效次数
VERSION_COUNT 子游标版本数(多版本表示绑定变量不安全)
SHARABLE_MEM 共享内存占用(字节) Oracle

六、优化器与环境

表格
列名 说明
OPTIMIZER_COST CBO 估算成本 Oracle
OPTIMIZER_MODE 优化器模式(ALL_ROWS/FIRST_ROWS 等) Oracle
PARSING_SCHEMA_NAME 解析用户名
MODULE/ACTION 应用模块名(DBMS_APPLICATION_INFO)
SQL_PROFILE 使用的 SQL Profile 名称

七、DBA 常用查询(直接套用)

  1. 某快照区间 TOP 耗时 SQL

SELECT s.snap_id,
       h.sql_id,
       h.elapsed_time_delta / 1e6 AS elapsed_sec,
       h.cpu_time_delta / 1e6 AS cpu_sec,
       h.executions_delta,
       ROUND(h.elapsed_time_delta /
             DECODE(h.executions_delta, 0, 1, h.executions_delta) / 1e6,
             3) AS avg_etime_sec
  FROM dba_hist_sqlstat h
  JOIN dba_hist_snapshot s
    ON h.snap_id = s.snap_id
   AND h.dbid = s.dbid
   AND h.instance_number = s.instance_number
 WHERE s.begin_interval_time BETWEEN SYSDATE - 1 AND SYSDATE
   AND h.executions_delta > 0
 ORDER BY h.elapsed_time_delta DESC;

      2.某 SQL_ID 历史性能趋势

SELECT s.begin_interval_time,
       h.executions_delta,
       h.buffer_gets_delta,
       h.disk_reads_delta,
       h.elapsed_time_delta / 1e6 AS elapsed_sec
  FROM dba_hist_sqlstat h
  JOIN dba_hist_snapshot s
 USING (snap_id, dbid, instance_number)
 WHERE h.sql_id = '&sql_id'
 ORDER BY s.begin_interval_time;

八、关键要点

  • _DELTA 用于性能分析(时段对比)
  • _TOTAL 用于累计统计(实例生命周期)
  • 必须配合 DBA_HIST_SNAPSHOT、DBA_HIST_SQLTEXT、DBA_HIST_SQL_PLAN 使用 Oracle
  • 不是所有 SQL 都会被 AWR 采样,只保存 TOP SQL


九、Oracle DBA_HIST_SQLSTAT 实战应用案例

配合 AWR 快照,精准定位慢 SQL、分析性能趋势、溯源性能抖动、做 SQL 优化复盘,生产 DBA 日常高频用法。

前置说明

  • 单位:时间字段 微秒,除以 1e6转秒
  • *_DELTA:快照间隔内增量值, 分析必用
  • 关联视图: DBA_HIST_SNAPSHOT(快照时间)、 DBA_HIST_SQLTEXT(SQL 原文)

案例 1:统计近 1 天业务 TOP 耗时 SQL(最常用)

需求

排查最近一天,执行量大、总耗时高、拖垮数据库的高危 SQL
SELECT st.sql_id,
       st.plan_hash_value,
       ss.begin_interval_time snap_time,
       st.executions_delta exec_cnt,
       ROUND(st.elapsed_time_delta / 1000000, 2) total_elapsed_sec,
       ROUND(st.elapsed_time_delta /
             DECODE(st.executions_delta, 0, 1, st.executions_delta) /
             1000000,
             3) avg_elapsed_sec,
       ROUND(st.cpu_time_delta / 1000000, 2) total_cpu_sec,
       st.buffer_gets_delta logic_read,
       st.disk_reads_delta phy_read,
       st.rows_processed_delta row_cnt,
       st.parsing_schema_name parse_user
  FROM dba_hist_sqlstat st
  JOIN dba_hist_snapshot ss
    ON st.snap_id = ss.snap_id
   AND st.dbid = ss.dbid
   AND st.instance_number = ss.instance_number
 WHERE ss.begin_interval_time >= SYSDATE - 1
   AND st.executions_delta > 0
 ORDER BY st.elapsed_time_delta DESC;

使用场景:每日性能巡检、业务卡顿溯源、晚间批处理慢查询排查

案例 2:单条 SQL 历史性能趋势分析

需求

已知 SQL_ID,查看多天执行频次、耗时、逻辑读变化,判断是否性能退化
SELECT ss.begin_interval_time stat_time,
       st.executions_delta exec_num,
       ROUND(st.elapsed_time_delta / 1e6, 2) total_elapsed_s,
       ROUND(st.elapsed_time_delta /
             DECODE(st.executions_delta, 0, 1, st.executions_delta) / 1e6,
             3) avg_cost_s,
       st.buffer_gets_delta buf_gets,
       st.disk_reads_delta disk_read
  FROM dba_hist_sqlstat st
 INNER JOIN dba_hist_snapshot ss
 USING (snap_id, dbid, instance_number)
 WHERE st.sql_id = '输入你的SQL_ID'
 ORDER BY ss.begin_interval_time;
判断结论
  1. 执行次数不变,单次耗时飙升 → 索引失效、统计信息过时、数据量暴涨
  2. 逻辑读暴增 → 执行计划走偏、全表扫描
  3. 物理读增多 → 缓存命中率下降、热数据溢出内存

案例 3:定位高 CPU 消耗 SQL

需求

数据库 CPU 持续冲高,定位元凶 SQL
SELECT st.sql_id,
       st.module,
       st.action,
       SUM(st.executions_delta) total_exec,
       ROUND(SUM(st.cpu_time_delta) / 1e6, 2) total_cpu_s,
       ROUND(SUM(st.elapsed_time_delta) / 1e6, 2) total_elapsed_s
  FROM dba_hist_sqlstat st
  JOIN dba_hist_snapshot ss
 USING (snap_id, dbid, instance_number)
 WHERE ss.begin_interval_time BETWEEN SYSDATE - 2 AND SYSDATE
 GROUP BY st.sql_id, st.module, st.action
 ORDER BY total_cpu_s DESC;

案例 4:定位高逻辑读 / 全表扫描 SQL(优化重点)

SELECT st.sql_id,
       st.executions_delta execs,
       st.buffer_gets_delta logic_read,
       st.disk_reads_delta disk_read,
       CASE
         WHEN st.buffer_gets_delta > st.rows_processed_delta * 20 THEN
          '疑似全表扫描'
         ELSE
          '读取正常'
       END sql_flag
  FROM dba_hist_sqlstat st
  JOIN dba_hist_snapshot ss
 USING (snap_id, dbid, instance_number)
 WHERE ss.begin_interval_time >= SYSDATE - 1
   AND st.executions_delta > 0
 ORDER BY st.buffer_gets_delta DESC;
优化方向:加索引、改写 SQL、分区裁剪、绑定执行计划

案例 5:排查硬解析严重的 SQL

LOADS_DELTA代表硬解析次数,数值大说明游标频繁失效、绑定变量使用不当
SELECT sql_id,
       plan_hash_value,
       loads_delta         hard_parse_cnt,
       invalidations_delta cursor_invalid,
       version_count       child_cursor_num
  FROM dba_hist_sqlstat st
  JOIN dba_hist_snapshot ss
 USING (snap_id, dbid, instance_number)
 WHERE ss.begin_interval_time >= SYSDATE - 1
   AND loads_delta > 10
 ORDER BY loads_delta DESC;
问题解决:统一 SQL 写法、使用绑定变量、稳定统计信息、设置游标共享

案例 6:业务高峰期慢 SQL 专项排查

需求:每日 9-10 点业务高峰卡顿,抓取该时段劣化 SQL

SELECT st.sql_id,
       ROUND(st.elapsed_time_delta / 1e6, 2) elapsed_s,
       st.executions_delta,
       st.buffer_gets_delta
  FROM dba_hist_sqlstat st
  JOIN dba_hist_snapshot ss
 USING (snap_id, dbid, instance_number)
 WHERE TRUNC(ss.begin_interval_time) = TRUNC(SYSDATE)
   AND TO_CHAR(ss.begin_interval_time, 'HH24') BETWEEN '09' AND '10'
 ORDER BY elapsed_s DESC;

案例 7:结合 SQL 文本 + 执行计划完整溯源

SELECT st.sql_id, st.plan_hash_value, st.executions_delta, dt.sql_text
  FROM dba_hist_sqlstat st
  LEFT JOIN dba_hist_sqltext dt
    ON st.sql_id = dt.sql_id
 WHERE st.sql_id = '&sql_id';
-- 再查历史执行计划
SELECT * FROM dba_hist_sql_plan WHERE sql_id = '&sql_id';


案例 8:近 24 小时 TOP 慢 SQL 完整版(生产直接执行)

SELECT ST.SQL_ID,
       SS.BEGIN_INTERVAL_TIME SNAP_TIME,
       ST.PARSING_SCHEMA_NAME USERNAME,
       ST.EXECUTIONS_DELTA EXEC_TIMES,
       ROUND(ST.ELAPSED_TIME_DELTA / 1000000, 2) TOTAL_ELAPSED_S,
       ROUND(ST.ELAPSED_TIME_DELTA /
             DECODE(ST.EXECUTIONS_DELTA, 0, 1, ST.EXECUTIONS_DELTA) /
             1000000,
             3) AVG_ELAPSED_S,
       ROUND(ST.CPU_TIME_DELTA / 1000000, 2) TOTAL_CPU_S,
       ST.BUFFER_GETS_DELTA LOGIC_READ,
       ST.DISK_READS_DELTA DISK_READ,
       ST.ROWS_PROCESSED_DELTA FETCH_ROWS,
       DBMS_LOB.SUBSTR(DT.SQL_TEXT, 60) SQL_TEXT
  FROM DBA_HIST_SQLSTAT ST
  JOIN DBA_HIST_SNAPSHOT SS
    ON ST.SNAP_ID = SS.SNAP_ID
   AND ST.DBID = SS.DBID
   AND ST.INSTANCE_NUMBER = SS.INSTANCE_NUMBER
  LEFT JOIN DBA_HIST_SQLTEXT DT
    ON ST.SQL_ID = DT.SQL_ID
 WHERE SS.BEGIN_INTERVAL_TIME >= SYSDATE - 1
   AND ST.EXECUTIONS_DELTA > 0
 ORDER BY ST.ELAPSED_TIME_DELTA DESC;


案例 9:近 24 小时 高 CPU 消耗 SQL

SELECT SQL_ID,
       PARSING_SCHEMA_NAME USER_NAME,
       SUM(EXECUTIONS_DELTA) TOTAL_EXEC,
       ROUND(SUM(CPU_TIME_DELTA) / 1000000, 2) TOTAL_CPU_SEC,
       ROUND(SUM(ELAPSED_TIME_DELTA) / 1000000, 2) TOTAL_ELAPSED_SEC,
       SUM(BUFFER_GETS_DELTA) TOTAL_LOGIC_READ
  FROM DBA_HIST_SQLSTAT S
  JOIN DBA_HIST_SNAPSHOT SH
 USING (SNAP_ID, DBID, INSTANCE_NUMBER)
 WHERE SH.BEGIN_INTERVAL_TIME >= SYSDATE - 1
 GROUP BY SQL_ID, PARSING_SCHEMA_NAME
 ORDER BY TOTAL_CPU_SEC DESC;


案例 10:近 24 小时 高逻辑读(全表扫描高危 SQL)

SELECT SQL_ID,
       EXECUTIONS_DELTA EXEC_CNT,
       BUFFER_GETS_DELTA LOGIC_READ,
       DISK_READS_DELTA PHY_READ,
       ROWS_PROCESSED_DELTA ROWS_CNT,
       CASE
         WHEN BUFFER_GETS_DELTA > ROWS_PROCESSED_DELTA * 30 THEN
          '严重全表扫描'
         WHEN BUFFER_GETS_DELTA > ROWS_PROCESSED_DELTA * 15 THEN
          '疑似全表扫描'
         ELSE
          '读取正常'
       END SQL_STATUS
  FROM DBA_HIST_SQLSTAT S
  JOIN DBA_HIST_SNAPSHOT SH
 USING (SNAP_ID, DBID, INSTANCE_NUMBER)
 WHERE SH.BEGIN_INTERVAL_TIME >= SYSDATE - 1
   AND EXECUTIONS_DELTA > 0
 ORDER BY BUFFER_GETS_DELTA DESC;

案例 11:排查硬解析过高 SQL(游标失效 / 无绑定变量)

SELECT SQL_ID,
       PLAN_HASH_VALUE,
       LOADS_DELTA         HARD_PARSE_NUM,
       INVALIDATIONS_DELTA CURSOR_INVALID,
       VERSION_COUNT       CHILD_CURSOR
  FROM DBA_HIST_SQLSTAT S
  JOIN DBA_HIST_SNAPSHOT SH
 USING (SNAP_ID, DBID, INSTANCE_NUMBER)
 WHERE SH.BEGIN_INTERVAL_TIME >= SYSDATE - 1
   AND LOADS_DELTA > 5
 ORDER BY LOADS_DELTA DESC;

案例 12:指定 SQL_ID 历史性能走势(填入 SQL_ID 直接查)

SELECT TO_CHAR(SH.BEGIN_INTERVAL_TIME, 'YYYY-MM-DD HH24:MI') STAT_TIME,
       S.EXECUTIONS_DELTA EXEC_NUM,
       ROUND(S.ELAPSED_TIME_DELTA / 1000000, 2) ELAPSED_SEC,
       S.BUFFER_GETS_DELTA BUFFER_GETS,
       S.DISK_READS_DELTA DISK_READS
  FROM DBA_HIST_SQLSTAT S
  JOIN DBA_HIST_SNAPSHOT SH
 USING (SNAP_ID, DBID, INSTANCE_NUMBER)
 WHERE S.SQL_ID = '&INPUT_SQL_ID'
 ORDER BY SH.BEGIN_INTERVAL_TIME;


生产落地实用经验

  1. 快照保留策略默认 AWR 保留 8 天,调大保留周期方便回溯周 / 月级别性能问题
exec dbms_workload_repository.modify_snapshot_settings(retention=>43200,interval=>30);


  1. 区分好坏 SQL 核心指标
  • 好 SQL:执行快、逻辑读低、CPU 占比合理、无大量物理读
  • 坏 SQL:单次执行慢、批量执行量大、高逻辑读、高硬解析
  1. 优化复盘流程 DBA_HIST_SQLSTAT发现问题 → 查看历史执行计划 → 优化改写 / 加索引 → 再次通过该视图对比优化前后耗时、逻辑读变化
  2. 限制AWR 是采样数据, 极低频 SQL 不会被记录,实时瞬时卡顿要配合 v$sqlstat、 v$session排查



来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12798004/viewspace-3117875/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle ACE。ACOUG核心成员,Oracle用户组年轻专家。熟悉Oracle的体系结构,擅长Oracle数据库架构规划、SQL优化、OWI方面性能的优化。曾服务于航天、航空、机车、大型制造行业数据库的维护以及系统开发工作,开发过基于Oracle数据库的大型ERP系统。
  • 博文量
    345
  • 访问量
    2477892