做Oracle性能优化的人几乎都遇到过这样的场景:一条SQL已经跑了几个小时,AWR报告里能看到它的总耗时,却无法知道它当前执行到哪一步、每一步处理了多少行、消耗了多少临时表空间。传统的执行计划只给出优化器的估算值,而估算与真实执行之间往往存在巨大偏差,这种偏差恰恰是性能问题的根源。Oracle SQL Monitor正是为了解决这个痛点而设计的工具,它可以对正在运行和刚刚结束的SQL进行实时级别的细粒度监控,把每一步操作的真实执行统计呈现出来。

SQL Monitor的触发条件与底层机制
实时SQL监控是Oracle 11g企业版随Real Application Testing选件引入的特性,后来在19c中被并入Database In-Memory选件的一部分能力描述,但核心功能一直保持稳定。它并非对所有SQL都生效,而是有明确的触发条件,理解这些条件是使用它的第一步。
第一种触发方式是并行执行的SQL。只要一条SQL使用了并行,Oracle就会自动将其纳入监控范围,无需任何手工干预。第二种是单次执行消耗超过5秒CPU时间或IO时间的SQL,这类SQL通常被认为是耗资源的,数据库会自动开启监控。除此之外,用户也可以通过在SQL文本中加入monitor提示强制开启,或者使用no_monitor提示显式关闭。
-- 强制开启监控 SELECT /*+ MONITOR */ COUNT(*) FROM big_table WHERE create_date > SYSDATE - 30; -- 强制关闭监控 SELECT /*+ NO_MONITOR */ COUNT(*) FROM small_table;
监控数据被记录在SGA中的一块循环使用的内存区域里,目标占用约为SGA的百分之五。当区域被写满时,最旧的监控记录会被清除。每条记录每隔一秒刷新一次统计信息,因此能看到接近实时的执行状态。监控记录默认保留一分钟,如果SQL执行结束后的记录被后续查询访问过,保留时间会延长,这也是为什么有时需要及时生成报告的原因。相关参数可以通过V$SQL_MONITOR和DBMS_SQLTUNE.REPORT_SQL_MONITOR配合管理。
三种常用的查看方式与核心视图
最常用的入口是V$SQL_MONITOR视图,它记录了每条被监控SQL的关键信息。其中最重要的几个字段需要熟练掌握:STATUS表示执行状态,QUEUED表示排队中,EXECUTING表示正在执行,DONE表示已完成;ELAPSED_TIME是累计耗时;CPU_TIME与IO_TIME分别对应处理器与IO消耗;PROCESS_NAME可以区分前台进程、并行从属进程或后台作业进程。
-- 查看当前正在执行的监控SQL
SELECT sql_id, status, username, elapsed_time/1000000 AS elapsed_sec,
cpu_time/1000000 AS cpu_sec, buffer_gets, disk_reads
FROM v$sql_monitor
WHERE status = 'EXECUTING'
ORDER BY elapsed_time DESC;第二个入口是SQL Monitoring明细页面。在SQL Developer或Enterprise Manager Cloud Control中找到对应的SQL,进入其监控页面后,可以看到可视化的计划树,每个步骤标注了实际行数、估算行数和耗时占比,偏差巨大的步骤会用醒目的方式提示。第三个入口是纯文本报告,通过DBMS_SQLTUNE.REPORT_SQL_MONITOR函数生成,适合在没有图形界面的生产环境中使用。
-- 生成最近一次监控的文本报告
SET LONG 1000000
SET LONGCHUNKSIZE 1000000
SET LINESIZE 200
SET PAGESIZE 0
SET HEADING OFF
SPOOL /tmp/monitor_report.txt
SELECT DBMS_SQLTUNE.REPORT_SQL_MONITOR(
type => 'TEXT',
report_level => 'ALL')
FROM dual;
SPOOL OFFtype参数除了TEXT还支持HTML和XML。HTML格式的报告包含交互式的活动图和并行执行细节,是发给开发人员分析的最佳载体。如果需要监控一条SQL的多次执行汇总,可以改用REPORT_SQL_MONITOR_LIST函数。另外,活动会话历史视图V$ACTIVE_SESSION_HISTORY与SQL Monitor的detail部分数据来源一致,两者交叉验证能进一步确认瓶颈所在。
结合估算偏差做SQL调优分析
拿到监控报告后,调优的核心工作是比较估算行数与实际行数的差异。优化器基于统计信息做出估算,一旦统计信息过期、数据分布倾斜或存在复杂的谓词组合,估算就可能严重偏离实际,从而选择了错误的连接方式或访问路径。
典型的例子是嵌套循环连接:如果优化器估算内表只返回十行,会选择嵌套循环,但实际返回了一千万行,执行时就会表现为大量的逻辑读和超长耗时。在监控报告的计划树中,这类步骤的估算行数与实际行数旁边通常会有明显的偏差标记,耗时的横向条形图也会集中在一两个步骤上。定位到偏差步骤后,可以采取收集更精确的统计信息、改用动态采样、添加复合索引或改写SQL等手段。
对于并行执行的SQL,监控报告还提供了每个并行从属进程的工作量分布。如果发现某个从属进程承担了绝大部分工作而其他进程几乎空闲,说明数据倾斜导致并行度利用不充分,此时需要考虑对分区键做调整或使用分桶策略让数据分布更均匀。
使用SQL Monitor还需要注意几个细节。监控本身有轻微开销,但一秒一次的采样频率对绝大多数系统可以忽略。监控记录是易失的,实例重启后消失,因此排查历史问题应尽快生成报告,或者配合AWR、ASH做长期留存。对于执行时间很短但被频繁调用的SQL,SQL Monitor并不适合,此时应该转向V$SQL的累计统计并结合SQL概要数据分析。掌握这些边界条件,SQL Monitor才能真正成为定位慢SQL的利器。
Oracle SQL MonitorSQL性能监控Oracle调优修改时间:2026-09-13 03:12:29