Oracle – Automatic Workload Respository AWR

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

Leave a Reply

Your email address will not be published. Required fields are marked *