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

190 lines
10 KiB
SQL

@@header
/*
*
* Author : Vishal Gupta
* Purpose : Display table/index where rowcount has changed by more then specified threshold
* Parameters : 1 - OWNER (% - wildchar, \ - escape char)
* 2 - Object Name (% - wildchar, \ - escape char)
* 3 - Partition Name (% - wildchar, \ - escape char)
* 4 - Object Type (% - wildchar, \ - escape char)
* 5 - Row Count Percent Threshold (Default Value 10)
* 6 - Where Clause
*
*
* Revision History:
* ===================
* Date Author Description
* --------- ------------ -----------------------------------------
* 03-Jul-15 Vishal Gupta Created
*
*/
/************************************
* INPUT PARAMETERS
************************************/
UNDEFINE owner
UNDEFINE object_name
UNDEFINE subobject_name
UNDEFINE object_type
UNDEFINE diff_rowcnt_percent
UNDEFINE WHERECLAUSE
DEFINE owner="&&1"
DEFINE object_name="&&2"
DEFINE subobject_name="&&3"
DEFINE object_type="&&4"
DEFINE diff_rowcnt_percent="&&5"
DEFINE WHERECLAUSE="&&6"
COLUMN _owner NEW_VALUE owner NOPRINT
COLUMN _object_name NEW_VALUE object_name NOPRINT
COLUMN _subobject_name NEW_VALUE subobject_name NOPRINT
COLUMN _object_type NEW_VALUE object_type NOPRINT
COLUMN _diff_rowcnt_percent NEW_VALUE diff_rowcnt_percent NOPRINT
set term off
SELECT CASE
WHEN INSTR('&&owner','.') != 0 THEN SUBSTR(UPPER('&&owner'),1,INSTR('&&owner','.')-1)
ELSE DECODE(UPPER('&&owner'),'','%',UPPER('&&owner'))
END "_owner"
, CASE
WHEN INSTR('&&owner','.') != 0 THEN SUBSTR(UPPER('&&owner'),INSTR('&&owner','.')+1)
ELSE DECODE(UPPER('&&object_name'),'','%',UPPER('&&object_name'))
END "_object_name"
, DECODE('&&subobject_name','','%','&&subobject_name') "_subobject_name"
, DECODE('&&object_type','','%','&&object_type') "_object_type"
, DECODE('&&diff_rowcnt_percent','','10','&&diff_rowcnt_percent') "_diff_rowcnt_percent"
FROM DUAL
;
set term on
PROMPT
PROMPT ***********************************************************************
PROMPT * S T A T I S T I C S C H A N G E
PROMPT *
PROMPT * Input Parameters
PROMPT * - Object Owner = '&&owner'
PROMPT * - Object Name = '&&object_name'
PROMPT * - SubObject Name = '&&subobject_name'
PROMPT * - Object Type = '&&object_type'
PROMPT * - Diff Row % = '&&diff_rowcnt_percent'
PROMPT * - Where Clause = '&&WHERECLAUSE'
PROMPT ***********************************************************************
COLUMN object_name HEADING "ObjectName" FORMAT a60
COLUMN subobject_name HEADING "SubObjectName" FORMAT a30
COLUMN object_type HEADING "Object|Type" FORMAT a18
COLUMN ANALYZETIME HEADING "AnalyzeTime" FORMAT a18
COLUMN prev_ANALYZETIME HEADING "Prev|AnalyzeTime" FORMAT a18
COLUMN rowcnt HEADING "RowCount" FORMAT 999,999,999,999
COLUMN prev_rowcnt HEADING "Prev|RowCount" FORMAT 999,999,999,999
COLUMN diff_rowcnt HEADING "Diff|RowCount" FORMAT 999,999,999,999
COLUMN diff_rowcnt_percent HEADING "Diff|Row|(%)" FORMAT 990.99
COLUMN SizeMB HEADING "Size|(MB)" FORMAT 9,999,999
COLUMN prev_SizeMB HEADING "Prev|Size|(MB)" FORMAT 9,999,999
COLUMN diff_SizeMB HEADING "Diff|Size|(MB)" FORMAT 9,999,999
WITH last_stat as
( select /*+ NO_MERGE MATERIALIZE */
obj#
, max(analyzetime) analyzetime
from sys.wri$_optstat_tab_history
GROUP BY obj#
)
, stats as
( SELECT /*+ NO_MERGE MATERIALIZE */
obj#
, analyzetime prev_analyzetime
, rowcnt prev_rowcnt
, blkcnt prev_blkcnt
FROM sys.wri$_optstat_tab_history h
)
select o.owner || '.' || o.object_name || NVL2(o.subobject_name,':' || o.subobject_name, '') object_name
, o.object_type object_type
, ROUND((NVL(tsp.num_rows,NVL(tp.num_rows,t.num_rows)) - s.prev_rowcnt)/s.prev_rowcnt * 100, 2) diff_rowcnt_percent
, NVL(tsp.num_rows,NVL(tp.num_rows,t.num_rows)) - s.prev_rowcnt diff_rowcnt
, ((NVL(tsp.blocks,NVL(tp.blocks,t.blocks)) - s.prev_blkcnt) * tbs.block_size) /1024/1024 diff_SizeMB
, TO_CHAR(NVL(tsp.last_analyzed,NVL(tp.last_analyzed,t.last_analyzed)),'DD-MON-YY HH24:MI:SS') analyzetime
, NVL(tsp.num_rows,NVL(tp.num_rows,t.num_rows)) rowcnt
, (NVL(tsp.blocks,NVL(tp.blocks,t.blocks)) * tbs.block_size) /1024/1024 SizeMB
, TO_CHAR(s.prev_analyzetime,'DD-MON-YY HH24:MI:SS') prev_analyzetime
, s.prev_rowcnt prev_rowcnt
, (s.prev_blkcnt * tbs.block_size) /1024/1024 prev_SizeMB
FROM last_stat ls
JOIN stats s ON ls.obj# = s.obj# AND s.prev_analyzetime = ls.analyzetime
JOIN dba_objects o ON ls.obj# = o.object_id
JOIN dba_tables t ON t.owner = o.owner AND t.table_name = o.object_name AND o.object_type = 'TABLE'
LEFT OUTER JOIN dba_tab_partitions tp ON tp.table_owner = o.owner AND tp.table_name = o.object_name
AND tp.partition_name = o.subobject_name AND o.object_type = 'TABLE PARTITION'
LEFT OUTER JOIN dba_tab_subpartitions tsp ON tsp.table_owner = o.owner AND tsp.table_name = o.object_name
AND tsp.subpartition_name = o.subobject_name AND o.object_type = 'TABLE SUBPARTITION'
JOIN dba_tablespaces tbs ON tbs.tablespace_name = NVL(tsp.tablespace_name,NVL(tp.tablespace_name,t.tablespace_name))
WHERE 1=1
AND o.owner LIKE upper('&&owner') ESCAPE '\'
AND o.object_name LIKE upper('&&object_name') ESCAPE '\'
AND NVL(o.subobject_name,'%') LIKE upper('&&subobject_name') ESCAPE '\'
AND NVL(o.object_type,'%') LIKE upper('&&object_type') ESCAPE '\'
AND ABS(ROUND((NVL(tsp.num_rows,NVL(tp.num_rows,t.num_rows)) - s.prev_rowcnt)/s.prev_rowcnt * 100, 2)) >= &&diff_rowcnt_percent
AND NVL(tsp.num_rows,NVL(tp.num_rows,t.num_rows)) < s.prev_rowcnt
&&WHERECLAUSE
UNION ALL
SELECT * FROM
(
WITH last_stat as
( select /*+ NO_MERGE MATERIALIZE */
obj#
, max(analyzetime) analyzetime
from sys.wri$_optstat_ind_history
GROUP BY obj#
)
, stats as
( SELECT /*+ NO_MERGE MATERIALIZE */
obj#
, analyzetime prev_analyzetime
, rowcnt prev_rowcnt
, leafcnt prev_leafcnt
FROM sys.wri$_optstat_ind_history h
)
select o.owner || '.' || o.object_name || NVL2(o.subobject_name,':' || o.subobject_name, '') object_name
, o.object_type object_type
, ROUND((NVL(isp.num_rows,NVL(ip.num_rows,i.num_rows)) - s.prev_rowcnt)/s.prev_rowcnt * 100, 2) diff_rowcnt_percent
, NVL(isp.num_rows,NVL(ip.num_rows,i.num_rows)) - s.prev_rowcnt diff_rowcnt
, ((NVL(isp.leaf_blocks,NVL(ip.leaf_blocks,i.leaf_blocks)) - s.prev_leafcnt) * tbs.block_size) /1024/1024 diff_SizeMB
, TO_CHAR(NVL(isp.last_analyzed,NVL(ip.last_analyzed,i.last_analyzed)),'DD-MON-YY HH24:MI:SS') analyzetime
, NVL(isp.num_rows,NVL(ip.num_rows,i.num_rows)) rowcnt
, (NVL(isp.leaf_blocks,NVL(ip.leaf_blocks,i.leaf_blocks)) * tbs.block_size) /1024/1024 SizeMB
, TO_CHAR(s.prev_analyzetime,'DD-MON-YY HH24:MI:SS') prev_analyzetime
, s.prev_rowcnt prev_rowcnt
, (s.prev_leafcnt * tbs.block_size) /1024/1024 prev_SizeMB
FROM last_stat ls
JOIN stats s ON ls.obj# = s.obj# AND s.prev_analyzetime = ls.analyzetime
JOIN dba_objects o ON ls.obj# = o.object_id
JOIN dba_indexes i ON i.owner = o.owner AND i.index_name = o.object_name AND o.object_type = 'INDEX'
LEFT OUTER JOIN dba_ind_partitions ip ON ip.index_owner = o.owner AND ip.index_name = o.object_name
AND ip.partition_name = o.subobject_name AND o.object_type = 'INDEX PARTITION'
LEFT OUTER JOIN dba_ind_subpartitions isp ON isp.index_owner = o.owner AND isp.index_name = o.object_name
AND isp.subpartition_name = o.subobject_name AND o.object_type = 'INDEX SUBPARTITION'
JOIN dba_tablespaces tbs ON tbs.tablespace_name = NVL(isp.tablespace_name,NVL(ip.tablespace_name,i.tablespace_name))
WHERE 1=1
AND o.owner LIKE upper('&&owner') ESCAPE '\'
AND o.object_name LIKE upper('&&object_name') ESCAPE '\'
AND NVL(o.subobject_name,'%') LIKE upper('&&subobject_name') ESCAPE '\'
AND NVL(o.object_type,'%') LIKE upper('&&object_type') ESCAPE '\'
AND ABS(ROUND((NVL(isp.num_rows,NVL(ip.num_rows,i.num_rows)) - s.prev_rowcnt)/s.prev_rowcnt * 100, 2)) >= &&diff_rowcnt_percent
AND NVL(isp.num_rows,NVL(ip.num_rows,i.num_rows)) < s.prev_rowcnt
&&WHERECLAUSE
)
ORDER BY diff_rowcnt_percent asc
, diff_rowcnt asc
;
@@footer