全网最全面的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:
- 用户应用产生的 SQL
- 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 一般具有以下特征:
- SQL 文本多为小写(但这不是绝对特征)
- 对象名称中常含有 $ 符号,这是 Oracle 内部命名的长期习惯
- 某些列名中包含 #,用于存储内部编号或 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,发明两项计算机专利
- 两次获得国家部级奖