Oracle中如何监控SQL执行时间?

在 Oracle 数据库中,监控 SQL 语句的执行时间是性能调优和问题排查的关键环节。Oracle 提供了多种机制来捕获和分析 SQL 的执行耗时,以下是 常用且实用的方法,按使用场景分类说明:


✅ 一、实时监控:查看当前正在执行的 SQL 及其已运行时间

方法:查询 V$SESSION + V$SQL

sql 复制代码
SELECT 
    s.sid,
    s.serial#,
    s.username,
    s.status,
    s.machine,
    s.program,
    q.sql_text,
    s.last_call_et AS "Seconds_Running",  -- 当前操作已运行秒数
    q.elapsed_time / 1000000 AS "Elapsed_Sec_Total",  -- 该SQL总耗时(秒)
    q.cpu_time / 1000000 AS "CPU_Sec"
FROM 
    v$session s
JOIN 
    v$sql q ON s.sql_id = q.sql_id
WHERE 
    s.status = 'ACTIVE'
    AND s.username IS NOT NULL
    AND s.type != 'BACKGROUND';

🔍 说明:

  • last_call_et:当前调用已持续的秒数(单位:秒),对活跃会话非常有用
  • elapsed_time:该 SQL 自首次执行以来累计总耗时(微秒),除以 1e6 转为秒。
  • 此方法适用于实时抓取慢查询

✅ 二、历史监控:查看已执行 SQL 的性能统计(AWR / V$SQL)

Oracle 会自动在共享池中缓存 SQL 的执行统计信息(通过 V$SQL 视图)。

查询最近执行过的 SQL 及其平均/总耗时:

sql 复制代码
SELECT 
    sql_id,
    substr(sql_text, 1, 100) AS sql_preview,
    executions AS execs,
    ROUND(elapsed_time / 1000000, 2) AS total_sec,
    ROUND(elapsed_time / NULLIF(executions, 0) / 1000000, 4) AS avg_sec,
    ROUND(cpu_time / NULLIF(executions, 0) / 1000000, 4) AS avg_cpu_sec,
    last_active_time
FROM 
    v$sql
WHERE 
    executions > 0
    AND last_active_time > SYSDATE - 1  -- 过去24小时
ORDER BY 
    elapsed_time DESC;

⚠️ 注意:

  • V$SQL 中的数据是内存中的缓存,实例重启或 SQL 被老化(aged out)后会丢失。
  • 适合查看近期高频或高耗时 SQL

✅ 三、长期监控:使用 AWR(Automatic Workload Repository)

AWR 是 Oracle 企业版(Enterprise Edition)提供的自动性能数据仓库,默认每小时快照一次,保留 8 天。

查看某段时间内最耗时的 SQL(Top SQL by Elapsed Time):

sql 复制代码
-- 需要知道快照 ID(snap_id)
SELECT * FROM TABLE(
    DBMS_WORKLOAD_REPOSITORY.select_sql(
        begin_snap => 12345,
        end_snap   => 12346,
        sql_id     => NULL  -- NULL 表示返回 Top SQL
    )
);

或者使用标准 AWR 报告:

sql 复制代码
-- 生成 HTML 或文本格式的 AWR 报告(需 DBA 权限)
@$ORACLE_HOME/rdbms/admin/awrrpt.sql

✅ AWR 优势:

  • 持久化存储,不受内存老化影响;
  • 包含等待事件、I/O、CPU 等完整上下文;
  • 支持跨时间段对比。
    ❌ 缺点:仅限 Enterprise Edition,且需额外许可(Diagnostics Pack)。

✅ 四、会话级跟踪:启用 SQL Trace(10046 Event)

如果要精确分析某条 SQL 的执行细节(包括各阶段耗时、等待事件),可开启 SQL Trace。

步骤:

1. 开启当前会话跟踪:
sql 复制代码
ALTER SESSION SET sql_trace = TRUE;
-- 或更详细的 10046 trace(level 12 包含绑定变量和等待事件)
ALTER SESSION SET EVENTS '10046 trace name context forever, level 12';
2. 执行你的 SQL
sql 复制代码
SELECT * FROM large_table WHERE ...;
3. 关闭跟踪
sql 复制代码
ALTER SESSION SET sql_trace = FALSE;
-- 或
ALTER SESSION SET EVENTS '10046 trace name context off';
4. 找到 trace 文件位置
sql 复制代码
SELECT value FROM v$diag_info WHERE name = 'Default Trace File';
5. 使用 tkprof 格式化分析
bash 复制代码
tkprof tracefile.trc output.txt explain=user/pass sort=exeela

📊 输出包含:

  • Parse / Execute / Fetch 各阶段耗时
  • CPU time、Elapsed time、Disk reads
  • 执行计划
    💡 适用场景:深度性能诊断,但不适用于生产环境大规模开启

✅ 五、使用 DBMS_MONITOR 跟踪特定会话或客户端

可针对某个用户、服务名或会话开启跟踪:

sql 复制代码
-- 跟踪某个客户端程序(如 JDBC 应用)
BEGIN
  DBMS_MONITOR.client_id_trace_enable(
    client_id => 'MY_APP_USER',
    waits     => TRUE,
    binds     => TRUE
  );
END;
/

后续用 tkprof 分析生成的 trace 文件。


✅ 六、监控长时间运行的操作(Long Operations)

对于 DML、DDL、备份等长时间操作,可用:

sql 复制代码
SELECT 
    opname,
    target,
    sofar,
    totalwork,
    ROUND(sofar/totalwork*100, 2) AS pct_done,
    time_remaining,
    elapsed_seconds
FROM 
    v$session_longops
WHERE 
    totalwork > 0 
    AND sofar != totalwork;

🔒 权限说明

操作 所需权限
查询 V$SESSION, V$SQL SELECT ANY DICTIONARY 或 DBA 授予 V_$SESSION
生成 AWR 报告 SELECT_CATALOG_ROLEDBA
开启 SQL Trace ALTER SESSION(普通用户可开自己的),全局跟踪需 DBA

✅ 总结:如何选择?

场景 推荐方法
实时查看谁在跑慢 SQL V$SESSION + V$SQL(查 last_call_et
分析最近哪些 SQL 最耗时 V$SQLelapsed_time 排序
长期性能趋势分析 AWR 报告
深度诊断单条 SQL 10046 trace + tkprof
监控大事务/导入导出进度 V$SESSION_LONGOPS

相关推荐
岁岁种桃花儿20 小时前
MySQL从入门到精通系列:InnoDB记录存储结构
数据库·mysql
蜜獾云21 小时前
oracle查询所有的表名和注释
oracle
jiunian_cn21 小时前
【Redis】hash数据类型相关指令
数据库·redis·哈希算法
冉冰学姐21 小时前
SSM在线影评网站平台82ap4(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm框架·在线影评平台·影片分类
知识分享小能手1 天前
SQL Server 2019入门学习教程,从入门到精通,SQL Server 2019数据库的操作(2)
数据库·学习·sqlserver
爬山算法1 天前
Hibernate(84)如何在DevOps流程中使用Hibernate?
oracle·hibernate·devops
踩坑小念1 天前
秒杀场景下如何处理redis扣除状态不一致问题
数据库·redis·分布式·缓存·秒杀
萧曵 丶1 天前
MySQL 语句书写顺序与执行顺序对比速记表
数据库·mysql
Wiktok1 天前
MySQL的常用数据类型
数据库·mysql
曹牧1 天前
Oracle 表闪回(Flashback Table)
数据库·oracle