ITPub博客

首页 > 数据库 > Oracle > 第80期 追踪 SQL 性能随时间变化、执行计划是否漂移、资源消耗变化

第80期 追踪 SQL 性能随时间变化、执行计划是否漂移、资源消耗变化

原创 Oracle 作者:pxbibm 时间:2026-08-27 09:06:41 0 删除 编辑

先上sql语句,在详细讲解这条sql的作用,下面这条sql,在工作中经常使用。

select
to_char (b.END_INTERVAL_TIME,'yyyymmddhh24mi') shijian,
a.plan_hash_value plan_hash,
sum (a.EXECUTIONS_DELTA) execu_d,
sum (a.BUFFER_GETS_DELTA ) bg_d,
sum (a.DISK_READS_DELTA ) dr_d,
sum (a.ELAPSED_TIME_DELTA/1000000) et_d,
sum (a.CPU_TIME_DELTA/1000000)  ct_d,
sum (IOWAIT_DELTA/1000000) io_time,
sum (CLWAIT_DELTA/1000000) clus_time,
sum (APWAIT_DELTA/1000000) ap_time,
sum (ccwait_delta/1000000) cc_time,
decode (sum (a.EXECUTIONS_DELTA),0,sum (a.ELAPSED_TIME_DELTA/1000000),sum (a.ELAPSED_TIME_DELTA/1000000)/sum (a.EXECUTIONS_DELTA)) et_onetime
from
dba_hist_sqlstat a,
dba_hist_snapshot b
where
a.SNAP_ID =b.SNAP_ID
and a.INSTANCE_NUMBER=b.INSTANCE_NUMBER
and a.sql_id='&sql_id'
and b.END_INTERVAL_TIME > sysdate - 6
group by
to_char(b.END_INTERVAL_TIME,'yyyymmddhh24mi'),a.plan_hash_value
order by 1;

一、SQL 整体作用总结

核心用途:针对指定 SQL_ID,从 AWR 历史性能视图,按 AWR 采样时间 + 执行计划哈希值,统计近 6 天内该 SQL 的分段性能指标,用于追踪这条 SQL 性能随时间变化、执行计划是否漂移、资源消耗变化。

数据源: dba_hist_sqlstat(AWR SQL 统计增量数据) + dba_hist_snapshot(AWR 采样快照时间) 适用:Oracle 10g/11g/12c/19c(传统 AWR 架构,CDB 环境需要适配) 前提:数据库 AWR 自动采样正常开启,AWR 保留时长≥6 天,账号有 SELECT_CATALOG_ROLE权限

二、表与字段释义

2.1 两张核心 AWR 视图

  1. dba_hist_snapshot bAWR 快照表,数据库每隔默认 1 小时自动生成一次 snapshot(可调整采集间隔)
  • SNAP_ID:快照编号
  • INSTANCE_NUMBER:RAC 实例号
  • END_INTERVAL_TIME:该快照 采集结束时间(这个时间代表【上一个 snap ~ 当前 snap】这段周期的统计数据)
  1. dba_hist_sqlstata AWR 里 SQL 性能 增量 (delta)统计表, 不是累计值!

重点: xxx_DELTA = 两个 snapshot 间隔内新增的指标,不是自实例启动以来总和 。

每条记录代表:在 snap N → snap N+1这个时间段内,该 sql_id+plan_hash_value 产生的资源消耗

字段 含义 单位
EXECUTIONS_DELTA 间隔内总执行次数 次
BUFFER_GETS_DELTA 逻辑读(buffer gets)增量 块
DISK_READS_DELTA 物理读增量 块
ELAPSED_TIME_DELTA 总耗时 微秒(μs)
CPU_TIME_DELTA CPU 耗时 微秒(μs)
IOWAIT_DELTA IO 等待时间 微秒(μs)
CLWAIT_DELTA Cluster 集群等待时间(RAC 特有的全局缓存等待,gc 类等待) 微秒(μs)
APWAIT_DELTA Application 应用等待(锁、行锁、enqueue 等) 微秒(μs)
CCWAIT_DELTA Concurrency 并发等待(latch、mutex 等内部并发资源争抢) 微秒(μs)

2.2 select 字段拆解

to_char(b.END_INTERVAL_TIME,'yyyymmddhh24mi') shijian

AWR 快照结束时间, 代表这一行指标归属的时间窗口,格式 yyyyMMddHHmi(年月日时分)

a.plan_hash_value plan_hash

SQL 执行计划哈希值; 同一个 SQL_ID 如果 plan_hash_value 变了 = 执行计划漂移(这条 SQL 核心监控点)

sum(a.EXECUTIONS_DELTA) execu_d --窗口内总执行次数
sum(a.BUFFER_GETS_DELTA ) bg_d  --窗口内总逻辑读
sum(a.DISK_READS_DELTA ) dr_d   --窗口内总物理读

窗口内总执行次数、总逻辑读、总物理读

sum(a.ELAPSED_TIME_DELTA/1000000) et_d --总耗时
sum(a.CPU_TIME_DELTA/1000000)  ct_d    --CPU 时间
sum(IOWAIT_DELTA/1000000) io_time      --IO 等待
sum(CLWAIT_DELTA/1000000) clus_time    --RAC 集群等待
sum(APWAIT_DELTA/1000000) ap_time      --应用锁等待
sum(ccwait_delta/1000000) cc_time      --并发 latch 等待

/1000000:微秒 → 秒

et_d:总耗时;ct_d:CPU 时间;io_time:IO 等待;clus_time:RAC 集群等待;ap_time:应用锁等待;cc_time:并发 latch 等待

decode(sum(a.EXECUTIONS_DELTA),0,sum(a.ELAPSED_TIME_DELTA/1000000),sum(a.ELAPSED_TIME_DELTA/1000000)/sum(a.EXECUTIONS_DELTA)) et_onetime

单次平均执行耗时(秒)

  • 如果该时间段执行次数 = 0,直接取总耗时(防止除以 0 报错)
  • 否则 = 总耗时 ÷ 总执行次数

2.3 where 条件

a.SNAP_ID =b.SNAP_ID
and a.INSTANCE_NUMBER=b.INSTANCE_NUMBER

关联快照和 SQL 统计,RAC 环境必须匹配实例号,否则数据错乱

a.sql_id='&sql_id'

输入目标 SQL_ID,变量替换

b.END_INTERVAL_TIME > sysdate - 6

只查询 最近 6 天的 AWR 快照数据

2.4 group by + order by

group by to_char(b.END_INTERVAL_TIME,'yyyymmddhh24mi'),a.plan_hash_value
order by 1;

核心逻辑:同一时间窗口下,如果出现多个不同 plan_hash_value 会拆成多行。

直接肉眼就能识别: 什么时间点 SQL 换了执行计划,同时伴随单次耗时暴涨 / 逻辑读飙升

三、这条 SQL 能解决什么问题(生产高频场景)

场景 1:SQL 性能突然变差,定位是否【执行计划漂移】(最常用)

输出结果里,如果 同一个 sql_id,同一个时间段前后 plan_hash_value 发生变化,同时 et_onetime、 bg_d暴涨 → 实锤执行计划变更导致性能恶化。

典型:统计信息自动收集、绑定变量窥探、cursor invalid、基线失效引发计划突变。

场景 2:看 SQL 的资源消耗趋势(是否高峰期压力变大)

按时间顺序输出:

  • 看是不是业务高峰时执行量 execu_d上涨、物理读 dr_d、IO 等待 io_time上涨
  • 区分慢 SQL 根因:是 CPU 瓶颈?磁盘 IO 瓶颈?RAC 集群 gc 等待?还是应用锁等待?
    • ct_d 占 et_d 大部分 → CPU 瓶颈
    • io_time 很高 → 物理 IO 慢
    • clus_time 高 → RAC 节点间缓存传输瓶颈
    • ap_time 高 → 行锁、enqueue 锁冲突
    • cc_time 高 → latch/mutex 争抢(硬解析、库缓存争用)

场景 3:确认 SQL 是否在某个时间段没有执行

如果某个时间窗口 execu_d=0,说明这段时间该 SQL 完全没有跑。

场景 4:RAC 多实例汇总统计

group by + sum 会把同 snapshot、同 plan 的多个实例数据合并汇总,适合 RAC 整体观测这条 SQL 的全局负载。

四、缺陷 & 坑点(重点,生产容易踩)

  1. AWR 是采样数据,不是实时数据只能看历史,不能看当前正在跑的 SQL;实时要看 v$sqlstat / v$sql。 如果 AWR 采样间隔 1h,只能按小时粒度看,看不到分钟级抖动(可以调整 AWR 采集间隔)。
  2. END_INTERVAL_TIME 容易理解偏差 END_INTERVAL_TIME是快照 结束时间,该行指标代表【上一个 snap → 当前 snap】这一段时间, 不是这个时间点瞬间的数据。
  3. 如果 AWR Purge 清理了历史,会缺数据 sysdate-6如果超过 AWR 保留周期,部分时间段无结果; 可查询 dba_hist_wr_control 查看 AWR 保留天数。
  4. sql_id 相同,不同 plan_hash_value 会分行展示这个是优点,但排查时需要留意:同一时间多条 plan 代表同 SQL 同时有多套执行计划在跑(游标共享异常、绑定变量窥探典型特征)
  5. decode 的 et_onetime 存在小瑕疵当 execu_d=0,et_onetime 直接等于总耗时,业务上没有实际意义,仅用来规避除 0 异常。
  6. 权限问题普通用户默认查不了 dba_hist_*,需要 DBA 授予 SELECT_CATALOG_ROLE; 12c/19c CDB 架构,需要在 CDB 查询或者使用 PDB 对应的视图,否则查不到数据。
  7. 不区分并行执行该 SQL 没有过滤 PX并行信息,并行 SQL 的 elapsed_time 会包含并行总耗时,单次耗时解读要小心。

五、优化增强版(可直接线上使用,修复缺陷,增加关键指标)

select 
    to_char(b.END_INTERVAL_TIME,'yyyymmddhh24mi') shijian,
    a.plan_hash_value plan_hash,
    sum(a.EXECUTIONS_DELTA) execu_d,
    sum(a.BUFFER_GETS_DELTA ) bg_d,
    sum(a.DISK_READS_DELTA ) dr_d,
    round(sum(a.ELAPSED_TIME_DELTA/1000000),4) et_d,
    round(sum(a.CPU_TIME_DELTA/1000000),4)  ct_d,
    round(sum(IOWAIT_DELTA/1000000),4) io_time,
    round(sum(CLWAIT_DELTA/1000000),4) clus_time,
    round(sum(APWAIT_DELTA/1000000),4) ap_time,
    round(sum(ccwait_delta/1000000),4) cc_time,
    -- 增加单次逻辑读,判断是否计划变差
    decode(sum(a.EXECUTIONS_DELTA),0,0,round(sum(a.BUFFER_GETS_DELTA)/sum(a.EXECUTIONS_DELTA),2)) bg_onetime,
    decode(sum(a.EXECUTIONS_DELTA),0,0,round(sum(a.ELAPSED_TIME_DELTA/1000000)/sum(a.EXECUTIONS_DELTA),4)) et_onetime
from     
    dba_hist_sqlstat a,
    dba_hist_snapshot b
where 
    a.SNAP_ID =b.SNAP_ID
and a.INSTANCE_NUMBER=b.INSTANCE_NUMBER
and a.sql_id='&sql_id'
and b.END_INTERVAL_TIME >= sysdate - 6
group by 
    to_char(b.END_INTERVAL_TIME,'yyyymmddhh24mi'),a.plan_hash_value
order by 1,2;

六、配套后续排查动作(发现异常后)

  1. plan_hash 漂移: dbms_xplan.display_awr('&sql_id',&plan_hash) 查看新旧执行计划对比
  2. 物理读高:检查索引、统计信息、是否全表扫描
  3. RAC clus_time 高:排查 gc buffer busy、gc current 等待
  4. ap_time 高:查 dba_hist_active_sess_history 看锁等待事件


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

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