Oracle AWR 报告中的SQL来自哪儿?

全网最全面的Oracle AWR 专栏,持续更新中...

当 Oracle 在 AWR 报告(Automatic Workload Repository Report)的 SQL Statistics 部分展示 Top SQL 时,出于可读性考虑,它通常会截断较长的 SQL 文本,只显示 SQL ID 旁边的前几个词。

而在该部分的最后,会出现一个完整的列表 ------ Complete List of SQL Text。这个部分包含了每一个 SQL ID 的完整 SQL 文本,DBA 可以点击报告中的 SQL_ID,查看未被截断的完整 SQL 语句。这种点击方式不仅适用于前面各个 SQL 列表,也同样适用于 Oracle 12c 之后附加在 AWR 报告末尾的 ASH 报告(Active Session History Report)。

一、Complete List 的来源

Complete List of SQL Text 同时包含两类 SQL:

  1. 用户应用产生的 SQL
  2. Oracle 后台进程产生的 SQL

这些 SQL 可能是独立执行的语句,也可能是嵌套在 PL/SQL 代码块中的语句。通过观察 SQL 文本的特征,往往可以推测出该 SQL 的来源。

二、PL/SQL 调用的 SQL 特征

如果 SQL 是通过 PL/SQL 调用执行的,PL/SQL 解释器会对 SQL 文本进行特定格式的转换:

  • 整个 SQL 文本会被全部转为大写
  • 输入变量以 :Bn 的形式出现(例如 :B1, :B2, :B3)
  • 输出变量以 :On 的形式出现(例如 :O0, :O1, :O2)

例如下面这个典型的 PL/SQL 转换后的 SQL:

SQL 复制代码
INSERT INTO ORDERS ( ORDER_ID,  ORDER_DATE,  ORDER_MODE,  CUSTOMER_ID,  ORDER_STATUS,  WAREHOUSE_ID,  DELIVERY_TYPE,  DELIVERY_ADDRESS_ID,  COST_OF_DELIVERY,  WAIT_TILL_ALL_AVAILABLE,  CUSTOMER_CLASS,  CARD_ID,  INVOICE_ADDRESS_ID ) 
VALUES ( ORDERS_SEQ.NEXTVAL + :B8 ,  SYSTIMESTAMP ,  'online',  :B7 ,  1,  :B6 ,  'Standard',  :B1 ,  DBMS_RANDOM.VALUE(:B5 ,  :B4 ),  'ship_asap',  :B2 ,  :B3 ,  :B1 ) 
RETURNING ORDER_ID INTO :O0

这类 SQL 一眼就能看出是由 PL/SQL 引擎转换而来。

三、Oracle 内部 SQL 的特征

由 Oracle 内部机制生成的 SQL 一般具有以下特征:

  1. SQL 文本多为小写(但这不是绝对特征)
  2. 对象名称中常含有 $ 符号,这是 Oracle 内部命名的长期习惯
  3. 某些列名中包含 #,用于存储内部编号或 ID

典型示例包括:

  • 系统表:OBJ$, TAB$, USER$, UNDO$
  • 视图:V 开头(如 `VSQL`)
  • 内部基表:X 开头(如 `XKCBFWAIT`)

以下是一个典型的内部 SQL 示例:

SQL 复制代码
select i.obj#, i.ts#, i.file#, i.block#, i.intcols, i.type#, i.flags, i.property, 
i.pctfree$, i.initrans, i.maxtrans, i.blevel, i.leafcnt, i.distkey, i.lblkkey, i.dblkkey, 
i.clufac, i.cols, i.analyzetime, i.samplesize, i.dataobj#, nvl(i.degree, 1), nvl(i.instances, 1), 
i.rowcnt, mod(i.pctthres$, 256), i.indmethod#, i.trunccnt, nvl(c.unicols, 0), 
nvl(c.deferrable#+c.valid#, 0), nvl(i.spare1, i.intcols), i.spare4, i.spare2, i.spare6, 
decode(i.pctthres$, null, null, mod(trunc(i.pctthres$/256), 256)), nvl(i.evaledition#, 1), 
nvl(i.unusablebefore#, 0), nvl(i.unusablebeginning#, 0),  ist.cachedblk, ist.cachehit, ist.logicalread 
from ind$ i,  ind_stats$ ist,  
(select enabled,  min(intcols) unicols, min(to_number(bitand(defer, 1))) deferrable#, 
min(to_number(bitand(defer, 4))) valid# from cdef$ where obj#=:1 and enabled > 1 group by enabled) c 
where i.obj#=c.enabled(+) and i.obj# = ist.obj#(+) and i.bo#=:1 order by i.obj#

通过 $、# 等命名特征,可以较容易判断该 SQL 来自 Oracle 内部。

四、CURSOR_SHARING 对 SQL Text 的影响

Oracle 的初始化参数 CURSOR_SHARING 也会改变 SQL 文本的形态。

当 CURSOR_SHARING=FORCE 时,Oracle 会自动将包含字面值的 SQL 重写,把所有常量替换为系统生成的绑定变量::SYS_B_n (n 为序号,如 0、1、2、3......),例如:

SQL 复制代码
SELECT UNIQUE_BANK_ID FROM TABADM.MODT 
WHERE BANK_ID = :"SYS_B_0" AND CUM_SOURCE = :"SYS_B_1" 
AND PRIMARY_REF = :"SYS_B_2" AND ROWNUM = :"SYS_B_3" 
AND DEL_FLG != :"SYS_B_4" AND ENTITY_CRE_FLG = :"SYS_B_5"

这种机制让仅在字面值上不同的 SQL 能够共享相同的 Cursor,减少硬解析(Hard Parse),提升 Shared Pool 的利用效率。

五、总结

AWR 报告末尾的 Complete List of SQL Text 不仅仅是展示完整 SQL 文本,它其实是 DBA 判断 SQL 来源、识别系统活动模式的一个"显微镜"。

通过仔细观察 SQL 的结构、变量形式、命名习惯等细节,DBA 可以快速区分:

  • 哪些 SQL 来自业务系统
  • 哪些 SQL 来自 PL/SQL
  • 哪些 SQL 属于 Oracle 内部操作
  • 以及它们是否受参数 CURSOR_SHARING 的影响

这就是理解 AWR 中"这些 SQL 都是从哪儿来的"的关键。

号主在certview.oracle.com网站上的证书清单截图。

关于号主,姚远:

  • Oracle ACE(Oracle和MySQL数据库方向)
  • 华为云最有价值专家
  • 《MySQL 8.0运维与优化》的作者
  • 拥有数十项数据库认证
  • 曾任IBM公司数据库部门经理
  • 20+年DBA经验,服务2万+客户
  • 精通C和Java,发明两项计算机专利
  • 两次获得国家部级奖
相关推荐
曹牧34 分钟前
Oracle数据库中,将JSON字符串转换为多行数据
数据库·oracle·json
被摘下的星星1 小时前
MySQL count()函数的用法
数据库·mysql
末央&1 小时前
【天机论坛】项目环境搭建和数据库设计
java·数据库
徒 花1 小时前
数据库知识复习07
数据库·作业
素玥1 小时前
实训5 python连接mysql数据库
数据库·python·mysql
jnrjian1 小时前
text index 查看index column index定义 index 刷新频率 index视图
数据库·oracle
韶博雅2 小时前
emcc升级
oracle
瀚高PG实验室2 小时前
审计策略修改
网络·数据库·瀚高数据库
言慢行善2 小时前
sqlserver模糊查询问题
java·数据库·sqlserver
韶博雅2 小时前
emcc24ai
开发语言·数据库·python