查询总耗CPU最多与平均耗CPU最多的SQL语句

本文提供两种SQL查询语句,用于找出数据库中总耗CPU最多及平均耗CPU最多的前20个SQL语句。通过这些查询可以帮助数据库管理员快速定位性能瓶颈。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

总耗CPU最多的前20个SQL

SELECT TOP 20
    total_worker_time/1000 AS [总消耗CPU 时间(ms)],execution_count [运行次数],
    qs.total_worker_time/qs.execution_count/1000 AS [平均消耗CPU 时间(ms)],
    last_execution_time AS [最后一次执行时间],max_worker_time /1000 AS [最大执行时间(ms)],
    SUBSTRING(qt.text,qs.statement_start_offset/2+1, 
        (CASE WHEN qs.statement_end_offset = -1 
        THEN DATALENGTH(qt.text) 
        ELSE qs.statement_end_offset END -qs.statement_start_offset)/2 + 1) 
    AS [使用CPU的语法], qt.text [完整语法],
    qt.dbid, dbname=db_name(qt.dbid),
    qt.objectid,object_name(qt.objectid,qt.dbid) ObjectName
FROM sys.dm_exec_query_stats qs WITH(nolock)
CROSS apply sys.dm_exec_sql_text(qs.sql_handle) AS qt
WHERE execution_count>1
ORDER BY  total_worker_time DESC

 

 

平均耗CPU最多的前20个SQL:

SELECT TOP 20
    total_worker_time/1000 AS [总消耗CPU 时间(ms)],execution_count [运行次数],
    qs.total_worker_time/qs.execution_count/1000 AS [平均消耗CPU 时间(ms)],
    last_execution_time AS [最后一次执行时间],min_worker_time /1000 AS [最小执行时间(ms)],
    max_worker_time /1000 AS [最大执行时间(ms)],
    SUBSTRING(qt.text,qs.statement_start_offset/2+1, 
        (CASE WHEN qs.statement_end_offset = -1 
        THEN DATALENGTH(qt.text) 
        ELSE qs.statement_end_offset END -qs.statement_start_offset)/2 + 1) 
    AS [使用CPU的语法], qt.text [完整语法],
    qt.dbid, dbname=db_name(qt.dbid),
    qt.objectid,object_name(qt.objectid,qt.dbid) ObjectName
FROM sys.dm_exec_query_stats qs WITH(nolock)
CROSS apply sys.dm_exec_sql_text(qs.sql_handle) AS qt
WHERE  execution_count>1
ORDER BY (qs.total_worker_time/qs.execution_count/1000) DESC

 

转载于:https://www.cnblogs.com/kandyvip/p/7001751.html

<think>好的,我现在需要在Oracle据库中查找过去一分钟内消CPU最多SQL语句及其对应的用户会话。首先,我得回忆一下Oracle的性能监控相关视图,比如v$session、v$sql等。可能还需要用到ASH(Active Session History)或者AWR(Automatic Workload Repository)报告,不过ASH可能更适合实时或近期的据。 用户提到要定位最近一分钟的情况,可能需要查询动态性能视图,特别是v$active_session_history,这个视图每秒钟采样一次活动会话,可以获取近期的据。但要注意权限问题,用户是否有访问这些视图的权限。 然后,需要关联哪些字段呢?SQL_ID和SESSION_ID应该是关键字段。可能需要关联v$session来获取用户名等信息。此外,CPU时间的计算可能需要用到v$sqlstats或v$sqlarea中的CPU_TIME字段,不过时间单位可能需要转换。 接下来,考虑到Oracle中CPU时间的统计可能分散在多个视图中,比如v$sqlstats中的CPU_TIME表示自SQL语句加载到库缓存以来的总CPU时间,但需要找出最近一分钟内的增量。这可能比较复杂,可能需要结合时间戳来过滤。 或者,可以通过v$active_session_history中的SESSION_STATE和WAIT_CLASS来筛选CPU活动。当SESSION_STATE为ON CPU时,说明会话正在消CPU资源。结合SAMPLE_TIME在最近一分钟的记录,统计各个SQL_ID和会话的CPU时间。 另外,可能需要使用到DBA_HIST_ACTIVE_SESS_HISTORY,但如果问题发生在最近,可能还没被AWR快照捕获,所以直接查询v$active_session_history更合适。 然后需要编写SQL语句,按SQL_ID和SESSION_ID分组,统计CPU时间总和,并按降序排列,取最高者。同时关联v$session获取用户名等信息。 需要注意的是,如果系统负载很高,可能需要考虑查询性能,避免对据库造成额外负担。另外,确保时间的过滤条件正确,比如使用SYSDATE - INTERVAL '1' MINUTE来限定时间范围。 可能还需要考虑ROWNUM或分析函来获取排名靠前的记录。但根据引用[1]提到的,使用order by和rownum时要注意嵌套查询,先排序再限制行,否则可能出现错误的结果。 总结步骤: 1. 查询v$active_session_history,过滤最近一分钟内的记录,且SESSION_STATE为ON CPU。 2. 关联v$session获取用户名等信息。 3. 按SQL_ID和SESSION_ID分组,统计CPU时间。 4. 按CPU时间降序排列,取最前面的记录。 5. 关联v$sqlarea获取完整的SQL文本。 可能遇到的问题:权限不足,视图不存在,时间范围处理不正确,或者统计方法有误。需要测试SQL语句的正确性,确保时间条件正确,并且正确关联各个视图。</think>### 分步解答 #### 步骤1:使用`v$active_session_history`筛选CPU Oracle的`v$active_session_history`视图记录了最近活跃会话的采样据(默认每秒一次)。通过以下条件筛选: - `session_state = 'ON CPU'`:表示会话处于消CPU状态 - `sample_time > SYSDATE - INTERVAL '1' MINUTE`:限制时间范围为最近1分钟 ```sql SELECT sql_id, session_id, session_serial#, COUNT(*) AS cpu_samples FROM v$active_session_history WHERE session_state = 'ON CPU' AND sample_time > SYSDATE - INTERVAL '1' MINUTE GROUP BY sql_id, session_id, session_serial# ORDER BY cpu_samples DESC; ``` #### 步骤2:关联`v$session`获取用户信息 通过`session_id`和`session_serial#`关联`v$session`,获取操作系统用户、据库用户和客户端程序信息: ```sql SELECT a.sql_id, s.osuser, s.username AS db_user, s.program, a.cpu_samples FROM ( SELECT sql_id, session_id, session_serial#, COUNT(*) AS cpu_samples FROM v$active_session_history WHERE session_state = 'ON CPU' AND sample_time > SYSDATE - INTERVAL '1' MINUTE GROUP BY sql_id, session_id, session_serial# ) a JOIN v$session s ON a.session_id = s.sid AND a.session_serial# = s.serial# ORDER BY a.cpu_samples DESC; ``` #### 步骤3:获取完整SQL文本 通过`sql_id`关联`v$sqlarea`,提取完整的SQL语句: ```sql SELECT sq.sql_text, t.* FROM ( -- 步骤2的查询结果 ) t JOIN v$sqlarea sq ON t.sql_id = sq.sql_id WHERE ROWNUM <= 10; -- 限制输出行 ``` #### 完整脚本 ```sql SELECT sq.sql_text, t.osuser, t.db_user, t.program, t.cpu_samples FROM ( SELECT a.sql_id, s.osuser, s.username AS db_user, s.program, a.cpu_samples FROM ( SELECT sql_id, session_id, session_serial#, COUNT(*) AS cpu_samples FROM v$active_session_history WHERE session_state = 'ON CPU' AND sample_time > SYSDATE - INTERVAL '1' MINUTE GROUP BY sql_id, session_id, session_serial# ) a JOIN v$session s ON a.session_id = s.sid AND a.session_serial# = s.serial# ORDER BY a.cpu_samples DESC ) t JOIN v$sqlarea sq ON t.sql_id = sq.sql_id WHERE ROWNUM <= 10; ``` ### 关键点说明 1. **采样精度**:`v$active_session_history`默认每秒采样一次,高并发场景可能存在误差[^2]。 2. **权限要求**:需授予用户`SELECT`权限于`v_$active_session_history`、`v_$session`等动态性能视图。 3. **时间范围**:使用`SYSDATE - INTERVAL '1' MINUTE`确保仅分析最近1分钟据。 4. **性能影响**:直接查询动态视图可能对高负载系统产生轻微影响,建议在非高峰时段执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值