AWR, Automatic Workload Respository
The Oracle AWR, Automatic Workload Respository, is tored in the SYSAUX tablespace. This post conatians information useful for purging/cleaning the AWR when it becomes large due to failure of cleanup jobs to remove partitions in the large AWR table, e.g. WRH$_ACTIVE_SESSION_HISTORY. Mainly Oracle 12c release 1.
-- check ASH history compared to retention period
select sysdate - a.sample_time ash,
sysdate - s.begin_interval_time snap,
c.RETENTION
from sys.wrm$_wr_control c,
(
select db.dbid,
min(w.sample_time) sample_time
from sys.v_$database db,
sys.Wrh$_active_session_history w
where w.dbid = db.dbid group by db.dbid
) a,
(
select db.dbid,
min(r.begin_interval_time) begin_interval_time
from sys.v_$database db,
sys.wrm$_snapshot r
where r.dbid = db.dbid
group by db.dbid
) s
where a.dbid = s.dbid
and c.dbid = a.dbid;
-- How much space is being used?
SELECT occupant_name "Item",
space_usage_kbytes/1048576 "Space Used (GB)",
schema_name "Schema",
move_procedure "Move Procedure"
FROM v$sysaux_occupants
WHERE occupant_name in ('SM/AWR','SM/OPTSTAT')
ORDER BY 1
-- Get orphaned ASH rows
SELECT COUNT(1) Orphaned_ASH_Rows FROM wrh$_active_session_history a
WHERE NOT EXISTS
(SELECT 1
FROM wrm$_snapshot
WHERE snap_id = a.snap_id
AND dbid = a.dbid
AND instance_number = a.instance_number
);
-- check ASH history compared to retention period
select sysdate - a.sample_time ash,
sysdate - s.begin_interval_time snap,
c.RETENTION
from sys.wrm$_wr_control c,
(
select db.dbid,
min(w.sample_time) sample_time
from sys.v_$database db,
sys.Wrh$_active_session_history w
where w.dbid = db.dbid group by db.dbid
) a,
(
select db.dbid,
min(r.begin_interval_time) begin_interval_time
from sys.v_$database db,
sys.wrm$_snapshot r
where r.dbid = db.dbid
group by db.dbid
) s
where a.dbid = s.dbid
and c.dbid = a.dbid;
-- Get current settings
select DBID, SNAP_INTERVAL, RETENTION, TOPNSQL from DBA_HIST_WR_CONTROL;
select
extract( day from snap_interval) *24*60+
extract( hour from snap_interval) *60+
extract( minute from snap_interval ) "Snapshot Interval (minutes)",
extract( day from retention) *24*60+
extract( hour from retention) *60+
extract( minute from retention ) "Retention Interval (minutes)"
from dba_hist_wr_control
-- Check snapshoits are being created properly
SELECT (CASE WHEN NUMTODSINTERVAL((SYSDATE - MAX(CAST(END_INTERVAL_TIME AS DATE))), 'DAY')
< SNAP_INTERVAL THEN 'OK AWR Snapshots are being collected' ELSE 'NOK Problems with Snapshot collection' END) "RESULT"
FROM DBA_HIST_SNAPSHOT, DBA_HIST_WR_CONTROL
GROUP BY SNAP_INTERVAL
-- Disable snapshots
BEGIN
DBMS_WORKLOAD_REPOSITORY.modify_snapshot_settings(
retention => 11520, -- Mins (43200 = 30 Days). Current value retained if NULL.(11520 is 8 days)
interval => 0); -- Mins. Current value retained if NULL. If zero --> snapshots are stopped
END;
/
-- Enable snapshots
BEGIN
DBMS_WORKLOAD_REPOSITORY.modify_snapshot_settings(
retention => 43200, -- Minutes (= 30 Days). Current value retained if NULL. (11520 is 8 days)
interval => 30); -- Minutes. Current value retained if NULL. If zero --> snapshots are stopped
END;
/
-- Get Objects at high end of tablespace
select * from (
select
owner,segment_name, partition_name, segment_type, max((block_id + blocks-1)*8192)/1024/1024 "HWM_MB"
from dba_extents where file_id=<file id for SYSAUX (2)>
group by owner,segment_name, partition_name, segment_type)
where HWM_MB > <Put size here e.g. 10000 for 10G>
order by 5 DESC
Move Segments to a temp SYSAUX to reorganize SYSAUX objects
• Move CTXSYS
• Move LogMiner
• Move DBAudit Tables
• Move LOB segments (BLOB and CLOB columns)
• Move Normal tables and rebuild indexes
• Move partitioned tables and rebuild partitioned indexes
• Move tables with LONG columns
• Move nested tables
• Move IOTs
• 12c – HEATMAP
• AQ datapump tables
exec ctxsys.DRI_MOVE_CTXSYS(TBS_NAME=>'SYSAUX_TEMP', PRINT_ONLY=>false)
select count(*), segment_type from dba_segments where tablespace_name = 'SYSAUX'
and owner = 'CTXSYS'
group by segment_type
exec SYS.DBMS_LOGMNR_D.SET_TABLESPACE('SYSAUX_TEMP')
exec DBMS_AUDIT_MGMT.move_dbaudit_tables('SYSAUX_TEMP')
BEGIN
dbms_audit_mgmt.set_audit_trail_location(
audit_trail_type => dbms_audit_mgmt.audit_trail_unified,
audit_trail_location_value => 'SYSAUX_TEMP');
END;
/
BEGIN
DBMS_AUDIT_MGMT.set_audit_trail_location(
audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD,--this moves table AUD$
audit_trail_location_value => 'SYSAUX_TEMP');
END;
/
BEGIN
DBMS_AUDIT_MGMT.set_audit_trail_location(
audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_FGA_STD,--this moves table FGA_LOG$
audit_trail_location_value => 'SYSAUX_TEMP');
END;
/
None of these move the CLI_ objects
PROCEDURE MOVE_DBAUDIT_TABLES
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
AUDIT_TRAIL_TBS VARCHAR2 IN DEFAULT
12c
--THIS ONE removed CLI_SWP* (very quickly!) – when the AUDIT objects are moved
-- they are recreated in the new tablespace
SQL> exec dbms_audit_mgmt.clean_audit_trail(audit_trail_type=>dbms_audit_mgmt.audit_trail_unified,use_last_arch_timestamp=>FALSE);
BLOB and CLOB Segments
General
alter table <owner>.<table_name> move lob(<column name>) store as ( tablespace sysaux_temp );
Find Generate Move LOB Commands
SELECT 'alter table '||owner||'.'||TABLE_NAME||
' move lob('||COLUMN_NAME||') store as (tablespace SYSAUX_TEMP);' "move lob script",
DATA_TYPE
FROM dba_tab_columns
WHERE DATA_TYPE IN ('CLOB','BLOB')
AND table_name IN (SELECT table_name
FROM dba_tables
WHERE tablespace_name='SYSAUX'
and partitioned = 'NO'
and NESTED = 'NO')
and owner = 'SYS'
This will generate commands that will work for normal (non-partitioned and non-nested) tables.
Partitioned table commands are different
Move to SYSAUX_TEMP
alter table WRH$_SQL_PLAN move lob(other_xml) store as ( tablespace sysaux_temp )
12c
alter table WRH$_SQLTEXT move lob(SQL_TEXT) store as ( tablespace sysaux_temp )
Move back to SYSAUX
alter table WRH$_SQL_PLAN move lob(other_xml) store as ( tablespace sysaux )
12c
alter table WRH$_SQLTEXT move lob(SQL_TEXT) store as ( tablespace sysaux )
alter table WRI$_ADV_RATIONALE move lob(ATTR5) store as ( tablespace sysaux_temp )
alter table WRI$_DBU_FEATURE_USAGE move lob(FEATURE_INFO) store as ( tablespace sysaux_temp )
And for partitioned tables, example:
Find the LOB PARTITION name
Find the table name from dba_lobs
Find the column name by DESC’ing the table
select 'alter table <table name> move partition '
||partition_name||' lob(<column name>) '||' store as (tablespace SYSAUX_TEMP);'
from dba_tab_partitions where table_name = '<table name>'
select 'alter table WRI$_OPTSTAT_HISTHEAD_HISTORY move partition '
||partition_name||' lob(EXPRESSION) '||' store as (tablespace SYSAUX_TEMP);'
from dba_tab_partitions where table_name = 'WRI$_OPTSTAT_HISTHEAD_HISTORY'
Normal Tables and Indexes
Generate Table Move (to SYSAUX_TEMP) Scripts
select 'alter table '||owner||'.'||segment_name||' move tablespace sysaux_temp;'
from dba_segments where segment_type = 'TABLE' and tablespace_name = 'SYSAUX'and owner = 'SYS'
Generate Index Rebuild (to SYSAUX_TEMP) Scripts
select 'alter index '||owner||'.'||index_name||' rebuild tablespace SYSAUX_TEMP;'
from dba_indexes where status = 'UNUSABLE'
and tablespace_name = 'SYSAUX'
Partitioned tables and Indexes
Move table partitions to SYSAUX_TEMP
select 'alter table '||owner||'.'||segment_name||' move partition '||partition_name||' tablespace sysaux_temp;'
from dba_segments where segment_type = 'TABLE PARTITION' and tablespace_name = 'SYSAUX'
order by segment_name
Rebuild Index Partitions in SYSAUX_TEMP
They become USABLE again and are rebuilt in SYSAUX_TEMP
select 'alter index '||index_name|| ' rebuild partition '||
partition_name||' tablespace SYSAUX_TEMP;' from dba_ind_partitions
where status = 'UNUSABLE'
and tablespace_name = 'SYSAUX'
Move to SYSAUX_TEMP
select 'alter table '||owner||'.'||segment_name ||' move tablespace SYSAUX_TEMP;'
from dba_segments where segment_name like '%==' and tablespace_name = 'SYSAUX'
and segment_type = 'NESTED TABLE'
Index-Organized Tables
IOT
Find the table concerned and shrink it
Enable row movement on the table first (if not already enabled)
Display row_movement
select owner,table_name, row_movement from dba_tables where table_name in
(select table_name from dba_indexes where index_name like '%IOT%' and tablespace_name = 'SYSAUX')
GSMADMIN_INTERNAL – may not be required to move this – see
WMSYS
CTXSYS – these should have been moved with the move proc but may not have been
IOT Indexes
alter table AQ$_ALERT_QT_H shrink space cascade;
12c - HEATMAP
See MOS
Doc ID 2024036.1
HEATMAP Segment Size Is Large In SYSAUX Even When Heatmap=Off (Doc ID 2024036.1)
This is not the same as my problem – but the solution to my HEATMAP problem is in this document
SQL> show parameter HEAT_MAP;
NAME TYPE VALUE
------------------------------------ -------------------------------------------- ------------------------------
heat_map string OFF
ALTER SYSTEM SET "_drop_stat_segment"=1 scope=memory;
Heatmap is dropped
AQ DATAPUMP Tables
Examples
alter table "AQ$_KUPC$DATAPUMP_QUETAB_2_P" move tablespace sysaux_temp;
alter table "AQ$_KUPC$DATAPUMP_QUETAB_2_S" move tablespace sysaux_temp;
Tables with LONG columns
Display Tables with LONG Columns
SELECT TABLE_NAME,COLUMN_NAME,DATA_TYPE
FROM dba_tab_columns
WHERE DATA_TYPE IN ('LONG','LONG RAW')
AND table_name IN (SELECT table_name
FROM dba_tables
WHERE tablespace_name='SYSAUX')
Some tables with long columns do not contain data- these can be truncated directly.
For tables with LONG columns that contain data AND there is no data in the LONG column:
• create a temporary table with the data without the LONG column(s)
• truncate the table
• insert the rows back into the table
WRI$_ADV_SQLT_PLAN
Doc ID 2205210.1
create table SQLT_PLANS_TEMP as select
TASK_ID, OBJECT_ID, ATTRIBUTE, PLAN_HASH_VALUE, PLAN_ID,STATEMENT_ID, TIMESTAMP,
REMARKS, OPERATION, OPTIONS, OBJECT_NODE, OBJECT_OWNER, OBJECT_NAME, OBJECT_ALIAS,
OBJECT_INSTANCE,OBJECT_TYPE,OPTIMIZER,SEARCH_COLUMNS,ID,PARENT_ID,DEPTH,POSITION,
COST,CARDINALITY,BYTES,OTHER_TAG,PARTITION_START,PARTITION_STOP,PARTITION_ID,
DISTRIBUTION,CPU_COST,IO_COST,TEMP_SPACE,ACCESS_PREDICATES,FILTER_PREDICATES,
PROJECTION,TIME,QBLOCK_NAME,OTHER_XML from WRI$_ADV_SQLT_PLANS
select count(*) from WRI$_ADV_SQLT_PLANS where other is not null
select count(*) from SQLT_PLANS_TEMP
select * from SQLT_PLANS_TEMP
truncate table WRI$_ADV_SQLT_PLANS
insert into WRI$_ADV_SQLT_PLANS
select
TASK_ID,OBJECT_ID,ATTRIBUTE, PLAN_HASH_VALUE, PLAN_ID,STATEMENT_ID, TIMESTAMP,
REMARKS, OPERATION, OPTIONS, OBJECT_NODE, OBJECT_OWNER, OBJECT_NAME, OBJECT_ALIAS,
OBJECT_INSTANCE, OBJECT_TYPE,OPTIMIZER, SEARCH_COLUMNS, ID, PARENT_ID, DEPTH,POSITION,
COST, CARDINALITY, BYTES, OTHER_TAG,PARTITION_START,PARTITION_STOP,PARTITION_ID,
NULL,DISTRIBUTION,CPU_COST, IO_COST,TEMP_SPACE,ACCESS_PREDICATES,FILTER_PREDICATES,
PROJECTION,TIME,QBLOCK_NAME, OTHER_XML from SQLT_PLANS_TEMP
create table PLAN_temp as select
SIGNATURE, CATEGORY, OBJ_TYPE, PLAN_ID, STATEMENT_ID, XPL_PLAN_ID, TIMESTAMP,
REMARKS, OPERATION, OPTIONS, OBJECT_NODE, OBJECT_OWNER, OBJECT_NAME,
OBJECT_ALIAS, OBJECT_INSTANCE, OBJECT_TYPE, OPTIMIZER, SEARCH_COLUMNS, ID,
PARENT_ID, DEPTH, POSITION, COST,CARDINALITY,BYTES,OTHER_TAG,PARTITION_START,
PARTITION_STOP,PARTITION_ID,DISTRIBUTION,CPU_COST,IO_COST,TEMP_SPACE,
ACCESS_PREDICATES,FILTER_PREDICATES,PROJECTION,TIME,QBLOCK_NAME,OTHER_XML
from SQLOBJ$PLAN
truncate table SQLOBJ$PLAN
insert into SQLOBJ$PLAN select
SIGNATURE, CATEGORY, OBJ_TYPE, PLAN_ID, STATEMENT_ID, XPL_PLAN_ID, TIMESTAMP, REMARKS, OPERATION,
OPTIONS, OBJECT_NODE,OBJECT_OWNER,OBJECT_NAME,OBJECT_ALIAS,OBJECT_INSTANCE,OBJECT_TYPE,
OPTIMIZER,SEARCH_COLUMNS,ID,PARENT_ID,DEPTH,POSITION,COST,CARDINALITY,BYTES,OTHER_TAG,
PARTITION_START,PARTITION_STOP,PARTITION_ID,NULL,DISTRIBUTION,CPU_COST,IO_COST,TEMP_SPACE,
ACCESS_PREDICATES,FILTER_PREDICATES,PROJECTION,TIME,QBLOCK_NAME,OTHER_XML from PLAN_TEMP;
commit
select count(*) from SQLOBJ$PLAN
Check ADDM Jobs – Shows AWR is Working
If there are unusable indexes or other problems, ADDM tasks may not have a status of ‘COMPLETED’
This query shows ADDM tasks
select owner || '/' || advisor_name as owner_adv
, task_id || '/' || task_name as task_id_name
, created
, (execution_end - execution_start)*86400 as exe_duratn
, (execution_end - created) * 86400 as exe_creatn
, how_created
, status
, 'Description: ' || description as task_desc
, 'Error Msg : ' || error_message as error_msg
from (select t.*, rank() over (order by execution_end desc) rnk
from dba_advisor_tasks t) dat
where dat.rnk <= 50
and 1 = 1
order by created desc;
Check Object Validity and Recompile
Select count(*) from dba_objects where status <> 'VALID'
@?/rdbms/admin/utlrp.sql