Files
oracle/Kevin_Meade/showtopcpu11g.sql
2026-03-12 21:23:47 +01:00

125 lines
4.5 KiB
SQL

--
-- create a multi-part report on database SQL by instance
-- grouping SQL into powers of ten based on cpu consumed
-- in order to see easily the top 1% of queries that are most busy
--
set linesize 999
set pagesize 50000
set feedback 1
set trimspool on
set trimout on
set doc off
clear breaks
clear computes
set echo off
-- alter session set nls_date_format = 'dd-mon-rrrr hh24:mi:ss';
select * from v$version
/
select inst_id
,instance_name
,startup_time
,round((sysdate-startup_time),1) up_days
,round(round((sysdate-startup_time),1)*24) maximum_cache_hours
,to_char(sysdate,'dd-mon-rrrr hh24:mi:ss') right_now
from gv$instance
order by inst_id
/
--
-- show how long the database has been up, how many cpus are available, and thus the theoretical CPU available
--
select inst_id
,instance_name
,(select cpu_count_highwater from sys.v_$license) cpu_count
,round((round((sysdate-startup_time),1)*24)*(select cpu_count_highwater from sys.v_$license)) available_cpu_hours
from gv$instance
order by inst_id
/
col sql_text format a700 trunc
col sql_text clear
col sql_text format a700 trunc
col pct_total format 990
compute sum of sql_statements on inst_id
compute sum of sql_statements on report
compute sum of db_pct_total on inst_id
compute sum of db_pct_total on report
compute sum of running_consumed_cpu_hours on report
break on inst_id skip page on report
--
-- use a logarithmic scale to plot cpu consumtion of all queries in the cache
-- we can use this to zero in on the top consumers
-- notice we exclude PLSQL CALLS but not the sql inside these calls
-- this gives us the true SQL workload
--
select
inst_id
,cpu_time_log10
,sql_statements
,cpu_time_rounded,round(cpu_time) cpu_time
,round(100*ratio_to_report(cpu_time) over(partition by inst_id)) inst_pct_total
,round(100*ratio_to_report(cpu_time) over()) db_pct_total
,round(sum(cpu_time) over (partition by inst_id order by cpu_time_log10)) running_cpu_time
,round(round(sum(cpu_time) over (partition by inst_id order by cpu_time_log10))/60/60,2) running_consumed_cpu_hours
from (
select
inst_id
,trunc(log(10,mycpu_time)) cpu_time_log10
,count(*) sql_statements
,power(10,trunc(log(10,mycpu_time))) cpu_time_rounded
,sum(mycpu_time) cpu_time
from (
select inst_id,case when cpu_time <= 0 then 1 else cpu_time end/1000000 mycpu_time
from gv$sqlarea
where trim(upper(sql_text)) not like 'BEGIN%'
and trim(upper(sql_text)) not like 'DECLARE%'
and trim(upper(sql_text)) not like 'CALL%'
)
group by trunc(log(10,mycpu_time)),inst_id
) a
order by inst_id,a.cpu_time_log10
/
clear computes
col module format a30 word
col sec_per_exec format 999999990.0
--compute sum of cpu_seconds on inst_id , report
break on inst_id skip page
--
-- show use the actual SQL that exceeds some threshhold
-- these are the queries we want to concentrate on
-- configure the last AND predicate to whatever is reasonable based on the above query
--
select inst_id
,sql_id
,child_number
,trunc(cpu_time/1000000) cpu_seconds
,trunc(elapsed_time/1000000) eplapsed_seconds
,executions
,round(trunc(elapsed_time/1000000)/decode(executions,0,null,executions),1) sec_per_exec
,round((sysdate-to_date(first_load_time,'rrrr-mm-dd/hh24:mi:ss'))*24) hours_in_cache
,module
-- ,address
,hash_value
,(select 'Open' from gv$open_cursor b where b.inst_id = a.inst_id and b.address = a.address and b.hash_value = a.hash_value and rownum = 1) open
/*
,case when sql_text like '%SELECT /*+ ORDERED NO_EXPAND USE_HASH%' or sql_text like '%FROM :Q%' or instr(sql_text,'CIV_GB') > 0 or instr(sql_text,'PIV_GB') > 0 or instr(sql_text,'PIV_SSF') > 0 or instr(sql_text,'SWAP_JOIN_INPUTS') > 0 then 'Slave'
when sql_text like '%SELECT /*+ Q%' then 'Query'
else (select 'Yes' from gv$sql_plan b where b.inst_id = a.inst_id and b.address = a.address and b.hash_value = a.hash_value and b.child_number = a.child_number and b.other_tag like 'PARALLEL%' and rownum = 1)
end parallel
*/
,sql_text
from gv$sql a
where trim(upper(sql_text)) not like 'BEGIN%'
and trim(upper(sql_text)) not like 'DECLARE%'
and trim(upper(sql_text)) not like 'CALL%'
and cpu_time/1000000 >= 1000
--and cpu_time/1000000 >= 100
order by 1,4,5
/