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,发明两项计算机专利
  • 两次获得国家部级奖
相关推荐
siriuuus3 小时前
MySQL 数据备份
数据库·mysql·备份
熊文豪3 小时前
KingbaseES数据库性能调优工具全面解析
数据库·kingbasees·金仓数据库·电科金仓
冠希陈、3 小时前
PHP7.4.33 安装sqlsrv扩展
数据库
光影34153 小时前
专利撰写与申请核心要点简报
前端·数据库·php
心灵宝贝3 小时前
申威ky10架构安装MongoDB 4.0.1(rpm包:mongodb-4.0.1-8.ky10.sw_64.rpm)详细步骤
数据库·mongodb·架构
一 乐4 小时前
口腔健康系统|口腔医疗|基于java和小程序的口腔健康系统小程序设计与实现(源码+数据库+文档)
java·数据库·vue.js·小程序·毕设
vivo互联网技术4 小时前
Redis key 消失之谜
数据库·redis·内存淘汰策略·redis抓包分析·机制分析
TDengine (老段)4 小时前
TDengine 数据函数 TAN 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
TDengine (老段)4 小时前
TDengine 数学函数 SQRT 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·1024程序员节