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 执行时间 |
| 列名 | 说明 |
|---|---|
| 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 名称 |
某快照区间 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;
不是所有 SQL 都会被 AWR 采样,只保存 TOP SQL
DBA_HIST_SQLSTAT 实战应用案例1e6转秒*_DELTA:快照间隔内增量值,
分析必用DBA_HIST_SNAPSHOT(快照时间)、
DBA_HIST_SQLTEXT(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;
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;
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;
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;
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;
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;
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';
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;
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;
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;
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;
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;
exec dbms_workload_repository.modify_snapshot_settings(retention=>43200,interval=>30);
DBA_HIST_SQLSTAT发现问题 → 查看历史执行计划 → 优化改写 / 加索引 → 再次通过该视图对比优化前后耗时、逻辑读变化v$sqlstat、
v$session排查
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12798004/viewspace-3117875/ ,如需转载,请注明出处,否则将追究法律责任。