177 lines
6.0 KiB
MySQL
177 lines
6.0 KiB
MySQL
|
|
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||
|
|
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||
|
|
|
||
|
|
SET LINESIZE 999 PAGESIZE 5000 TRIMOUT ON TRIMSPOOL ON
|
||
|
|
|
||
|
|
COL accessed_table HEAD Accessed_Table FOR a40
|
||
|
|
COL aindex_operation HEAD Plan_Operation FOR a70
|
||
|
|
COL aindex_predicates HEAD PREDICATES FOR a100 truncate
|
||
|
|
COL obj_alias_qbc_name FOR a40
|
||
|
|
COL options FOR a30
|
||
|
|
|
||
|
|
COL AAS FOR 9999.9
|
||
|
|
COL cpu_pct HEAD CPU FOR A5
|
||
|
|
COL wait_pct HEAD WAIT FOR A5
|
||
|
|
|
||
|
|
COL ela_sec_exec HEAD "ELA_SEC/EXEC" FOR 9999990.999
|
||
|
|
|
||
|
|
COL aindex_plan_hash_value HEAD PLAN_HASH_VALUE PRINT
|
||
|
|
COL aindex_sql_id HEAD SQL_ID NOPRINT
|
||
|
|
COL aindex_sql_child HEAD "CHILD" PRINT
|
||
|
|
COL aindex_sample_time HEAD SAMPLE_HOUR
|
||
|
|
COL projection FOR A520
|
||
|
|
|
||
|
|
COL pct_child HEAD "Activity %" FOR A8
|
||
|
|
COL pct_child_vis HEAD "Visual" FOR A12
|
||
|
|
|
||
|
|
COL aindex_id HEAD "ID" FOR 9999
|
||
|
|
COL aindex_parent_id HEAD "PID" FOR 9999
|
||
|
|
|
||
|
|
|
||
|
|
PROMPT
|
||
|
|
PROMPT -- Santa's Little (Index) Helper BETA v0.5 - by Tanel Poder ( https://tanelpoder.com )
|
||
|
|
|
||
|
|
WITH
|
||
|
|
tab AS (SELECT /*+ NO_MERGE */ owner, table_name, num_rows
|
||
|
|
FROM dba_tables
|
||
|
|
WHERE UPPER(table_name) LIKE
|
||
|
|
UPPER(CASE
|
||
|
|
WHEN INSTR('&2','.') > 0 THEN
|
||
|
|
SUBSTR('&2',INSTR('&2','.')+1)
|
||
|
|
ELSE
|
||
|
|
'&2'
|
||
|
|
END
|
||
|
|
) ESCAPE '\'
|
||
|
|
AND owner LIKE
|
||
|
|
CASE WHEN INSTR('&2','.') > 0 THEN
|
||
|
|
UPPER(SUBSTR('&2',1,INSTR('&2','.')-1))
|
||
|
|
ELSE
|
||
|
|
user
|
||
|
|
END ESCAPE '\'
|
||
|
|
),
|
||
|
|
ind AS (SELECT /*+ NO_MERGE */ owner, index_name, table_owner, table_name
|
||
|
|
FROM dba_indexes
|
||
|
|
WHERE (table_owner, table_name) IN (SELECT owner, table_name FROM tab)),
|
||
|
|
sample_times AS (
|
||
|
|
select * from dual
|
||
|
|
),
|
||
|
|
sq AS (
|
||
|
|
SELECT
|
||
|
|
count(*) samples
|
||
|
|
, ash.sql_id
|
||
|
|
, ash.sql_child_number
|
||
|
|
, ash.sql_plan_hash_value
|
||
|
|
, NVL(ash.sql_plan_line_id,1) sql_plan_line_id -- this is because simple "planless" operations like single-row insert
|
||
|
|
, ash.sql_plan_operation
|
||
|
|
, ash.sql_plan_options
|
||
|
|
, ash.session_state
|
||
|
|
, ash.wait_class
|
||
|
|
, ash.event
|
||
|
|
FROM
|
||
|
|
v$active_session_history ash
|
||
|
|
WHERE
|
||
|
|
1=1
|
||
|
|
AND ash.sql_plan_operation IN ('TABLE ACCESS', 'INDEX')
|
||
|
|
AND ash.sql_id LIKE '&1'
|
||
|
|
AND ash.sample_time BETWEEN &3 AND &4
|
||
|
|
GROUP BY
|
||
|
|
ash.sql_id
|
||
|
|
, ash.sql_child_number
|
||
|
|
, ash.sql_plan_hash_value
|
||
|
|
, NVL(ash.sql_plan_line_id,1)
|
||
|
|
, ash.sql_plan_operation
|
||
|
|
, ash.sql_plan_options
|
||
|
|
, ash.session_state
|
||
|
|
, ash.wait_class
|
||
|
|
, ash.event
|
||
|
|
),
|
||
|
|
ash_and_plan AS (
|
||
|
|
SELECT
|
||
|
|
plan.sql_id
|
||
|
|
, plan.child_number
|
||
|
|
, plan.plan_hash_value
|
||
|
|
, sq.samples seconds
|
||
|
|
, LPAD(TO_CHAR(ROUND(RATIO_TO_REPORT(sq.samples) OVER (PARTITION BY sq.sql_id, sq.sql_plan_hash_value) * 100, 1), 999.9)||' %',8) pct_child
|
||
|
|
, '|'||RPAD( NVL( LPAD('#', ROUND(RATIO_TO_REPORT(sq.samples) OVER (PARTITION BY sq.sql_id, sq.sql_plan_hash_value) * 10), '#'), ' '), 10,' ')||'|' pct_child_vis
|
||
|
|
--, LPAD(plan.id,4)||CASE WHEN parent_id IS NULL THEN ' ' ELSE ' <- ' END||LPAD(plan.parent_id,4) aindex_plan_id
|
||
|
|
, plan.id aindex_id
|
||
|
|
, plan.parent_id aindex_parent_id
|
||
|
|
, plan.operation ||' '|| plan.options || NVL2(plan.object_name, ' ['||plan.object_owner||'.'||plan.object_name ||']', null) aindex_operation
|
||
|
|
, plan.object_owner
|
||
|
|
, plan.object_name
|
||
|
|
, plan.object_type
|
||
|
|
, plan.cardinality
|
||
|
|
, stat.executions
|
||
|
|
, stat.elapsed_time
|
||
|
|
, sq.session_state
|
||
|
|
, sq.wait_class
|
||
|
|
, sq.event
|
||
|
|
, plan.object_alias || CASE WHEN plan.qblock_name IS NOT NULL THEN ' ['|| plan.qblock_name || ']' END obj_alias_qbc_name
|
||
|
|
, CASE WHEN plan.access_predicates IS NOT NULL THEN '[A:] '|| SUBSTR(plan.access_predicates,1,1994) END || CASE WHEN plan.filter_predicates IS NOT NULL THEN ' [F:] ' || SUBSTR(plan.filter_predicates,1,1994) END aindex_predicates
|
||
|
|
, plan.projection
|
||
|
|
FROM
|
||
|
|
v$sql_plan plan
|
||
|
|
, v$sqlstats_plan_hash stat
|
||
|
|
, sq
|
||
|
|
WHERE
|
||
|
|
1=1
|
||
|
|
AND sq.sql_id(+) = plan.sql_id
|
||
|
|
AND sq.sql_child_number(+) = plan.child_number
|
||
|
|
AND sq.sql_plan_line_id(+) = plan.id
|
||
|
|
AND sq.sql_plan_hash_value(+) = plan.plan_hash_value
|
||
|
|
--
|
||
|
|
AND sq.sql_id(+) = stat.sql_id
|
||
|
|
AND sq.sql_plan_hash_value(+) = stat.plan_hash_value
|
||
|
|
AND stat.sql_id = plan.sql_id
|
||
|
|
AND stat.plan_hash_value = plan.plan_hash_value
|
||
|
|
--
|
||
|
|
AND plan.sql_id LIKE '&1'
|
||
|
|
----
|
||
|
|
)
|
||
|
|
SELECT * FROM (
|
||
|
|
SELECT
|
||
|
|
SUM(ap.seconds) seconds
|
||
|
|
, ROUND(SUM(ap.seconds) / ((CAST(&4 AS DATE) - CAST(&3 AS DATE)) * 86400), 1) AAS
|
||
|
|
, LPAD(TO_CHAR(ROUND(SUM(CASE WHEN ap.session_state = 'ON CPU' THEN ap.seconds ELSE 0 END) / SUM(ap.seconds) * 100))||'%',4) cpu_pct
|
||
|
|
, LPAD(TO_CHAR(ROUND(SUM(CASE WHEN ap.session_state = 'WAITING' THEN ap.seconds ELSE 0 END) / SUM(ap.seconds) * 100))||'%',4) wait_pct
|
||
|
|
--, SUM(CASE WHEN ap.wait_class = 'User I/O' THEN ap.seconds ELSE 0 END) iowait_sec
|
||
|
|
, t.owner||'.'||table_name accessed_table
|
||
|
|
, ap.aindex_operation
|
||
|
|
, ap.cardinality plan_card
|
||
|
|
, t.num_rows table_rows
|
||
|
|
, ap.cardinality / NULLIF(t.num_rows,0) * 100 filter_pct
|
||
|
|
, ap.executions sql_execs
|
||
|
|
, ROUND(ap.elapsed_time / NULLIF(ap.executions,0) / 1000000,3) ela_sec_exec
|
||
|
|
, ap.aindex_predicates
|
||
|
|
, COUNT(DISTINCT ap.sql_id) dist_sqlids
|
||
|
|
, COUNT(DISTINCT ap.plan_hash_value) dist_plans
|
||
|
|
, MIN(ap.sql_id)
|
||
|
|
, MAX(ap.sql_id)
|
||
|
|
, ap.projection
|
||
|
|
FROM
|
||
|
|
ash_and_plan ap
|
||
|
|
, (SELECT tab.*, 'TABLE' object_type, tab.owner object_owner, tab.table_name object_name FROM tab
|
||
|
|
UNION ALL
|
||
|
|
SELECT tab.*, 'INDEX', ind.owner object_owner, ind.index_name object_name
|
||
|
|
FROM tab, ind
|
||
|
|
WHERE tab.owner = ind.table_owner AND tab.table_name = ind.table_name
|
||
|
|
) t
|
||
|
|
WHERE
|
||
|
|
ap.object_owner = t.object_owner AND ap.object_name = t.object_name AND SUBSTR(ap.object_type,1,5) = t.object_type
|
||
|
|
AND ap.seconds > 0
|
||
|
|
GROUP BY
|
||
|
|
t.owner
|
||
|
|
, t.table_name
|
||
|
|
, ap.aindex_operation
|
||
|
|
, t.num_rows
|
||
|
|
, ap.cardinality
|
||
|
|
, ap.executions
|
||
|
|
, ap.elapsed_time
|
||
|
|
, ap.aindex_predicates
|
||
|
|
, ap.projection
|
||
|
|
ORDER BY
|
||
|
|
seconds DESC
|
||
|
|
)
|
||
|
|
WHERE rownum <= 30
|
||
|
|
/
|