Files
notes/ASPM/asts_01.md
2026-03-12 22:01:38 +01:00

7.6 KiB

Setup

Check if Automatic SQL Tuning Sets (ASTS) is activated (enabled) and get the last execution time of the automatic schedule:

set lines 200
col task_name for a22

select * from dba_autotask_schedule_control where task_name = 'Auto STS Capture Task';

To enable:

exec dbms_auto_task_admin.enable(client_name => 'Auto STS Capture Task', operation => NULL, window_name => NULL);

No way to change the interval and maximum run time

To disable:

exec dbms_auto_task_admin.disable(client_name => 'Auto STS Capture Task', operation => NULL, window_name => NULL);

To manually run the job:

exec dbms_scheduler.run_job('ORA$_ATSK_AUTOSTS');

List last job executions:

col ACTUAL_START_DATE for a45

select ACTUAL_START_DATE,STATUS from dba_scheduler_job_run_details where JOB_NAME='ORA$_ATSK_AUTOSTS' 
order by ACTUAL_START_DATE desc fetch first 10 rows only;

More statistics on the task job:

WITH dsjrd AS
(
SELECT (TO_DATE('1','j')+run_duration-TO_DATE('1','j'))* 86400 duration_sec,
       (TO_DATE('1','j')+cpu_used-TO_DATE('1','j'))* 86400 cpu_used_sec
FROM dba_scheduler_job_run_details
WHERE job_name = 'ORA$_ATSK_AUTOSTS'
)
SELECT MIN(duration_sec) ASTS_Min_Time_Sec,
       MAX(duration_sec) ASTS_Max_Time_Sec,
       AVG(duration_sec) ASTS_Average_Time_Sec,
       AVG(cpu_used_sec) ASTS_Average_CPU_Sec
FROM dsjrd;

How many SQL statements we have actually in the SYS_AUTO_STS SQL Tuning Set (STS):

set lines 200
col name for a15
col description for a30
col owner for a10

select name, owner, description, created, last_modified, statement_count from dba_sqlset where name='SYS_AUTO_STS';

To purge all statements:

exec dbms_sqlset.drop_sqlset(sqlset_name => 'SYS_AUTO_STS', sqlset_owner => 'SYS');

How much space it takes in your SYSAUX tablesapce:

col table_name for a30
col table_size_mb for 999999.99
col total_size_mb for 999999.99

select
  table_name,
  round(sum(size_b) / 1024 / 1024, 3) as table_size_mb,
  round(max(total_size_b) / 1024 / 1024, 3) as total_size_mb
from
  (
    select
      table_name,
      size_b,
      sum(size_b) over() as total_size_b
      from
      (
        select
          segment_name as table_name,
          bytes as size_b
        from dba_segments
        where
          segment_name not like '%WORKSPA%'
          and owner = 'SYS'
          and (segment_name like 'WRI%SQLSET%' or segment_name like 'WRH$_SQLTEXT')
        union all
        select
          t.table_name,
          bytes as size_b
        from dba_segments s,
          (select
              table_name,
              segment_name
           from dba_lobs
           where table_name in ('WRI$_SQLSET_PLAN_LINES', 'WRH$_SQLTEXT')
           and owner = 'SYS'
          ) t
        where s.segment_name = t.segment_name
      )
  )
group by table_name
order by table_size_mb desc;

Test case

DROP TABLE test01 purge;
CREATE TABLE test01(id NUMBER, descr VARCHAR(50)) TABLESPACE users;
 
DECLARE
i NUMBER;
nbrows NUMBER;
BEGIN
  i:=1;
  nbrows:=50000;
  LOOP
    EXIT WHEN i>nbrows;
    IF (i=1) THEN
      INSERT INTO test01 VALUES(1,RPAD('A',49,'A'));
    ELSE
      INSERT INTO test01 VALUES(nbrows,RPAD('A',49,'A'));
    END IF;
    i:=i+1;
  END LOOP;
  COMMIT;
END;
/

CREATE INDEX test01_idx_id ON test01(id);

exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'test01', method_opt=>'FOR ALL INDEXED COLUMNS SIZE AUTO');

No histogram will be calculated:

col column_name for a20

select column_name,num_distinct,density,num_nulls,num_buckets,sample_size,histogram  
from user_tab_col_statistics  
where table_name='TEST01'; 



select  /*+ GATHER_PLAN_STATISTICS */ * FROM test01 WHERE id=1;

        ID DESCR
---------- --------------------------------------------------
         1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

The optimize we will choose a full scan:

SQL_ID  28stunrv2985c, child number 0
-------------------------------------
select  /*+ GATHER_PLAN_STATISTICS */ * FROM test01 WHERE id=1

Plan hash value: 262542483

-----------------------------------------------------------------------------------------------------------
| Id  | Operation         | Name   | Starts | E-Rows |E-Bytes| Cost (%CPU)| A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |        |      1 |        |       |   136 (100)|      1 |00:00:00.01 |     443 |
|*  1 |  TABLE ACCESS FULL| TEST01 |      1 |  25000 |   732K|   136   (0)|      1 |00:00:00.01 |     443 |
-----------------------------------------------------------------------------------------------------------

Wait for next Auto STS Capture Task schedule or run the job manually. The SQL_ID will be captured bu ASTS:

col SQLSET_NAME for a30
col PARSING_SCHEMA_NAME for a30

select SQLSET_NAME,PLAN_HASH_VALUE,PARSING_SCHEMA_NAME,BUFFER_GETS from DBA_SQLSET_STATEMENTS where SQL_ID='28stunrv2985c';

SQLSET_NAME                    PLAN_HASH_VALUE PARSING_SCHEMA_NAME            BUFFER_GETS
------------------------------ --------------- ------------------------------ -----------
SYS_AUTO_STS                         262542483 RED                                    453

Gather the stats again:

exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'test01', method_opt=>'FOR ALL INDEXED COLUMNS SIZE AUTO');

Oracle learned from its mistake and will calulate histograms:

COLUMN_NAME          NUM_DISTINCT    DENSITY  NUM_NULLS NUM_BUCKETS SAMPLE_SIZE HISTOGRAM
-------------------- ------------ ---------- ---------- ----------- ----------- ---------------
ID                              2     .00001          0           2       50000 FREQUENCY

Flush the shared pool and re-execute the query:

alter system flush shared_pool;

select  /*+ GATHER_PLAN_STATISTICS */ * FROM test01 WHERE id=1;

As expected, the index has been used:

SQL_ID  28stunrv2985c, child number 0
-------------------------------------
select  /*+ GATHER_PLAN_STATISTICS */ * FROM test01 WHERE id=1

Plan hash value: 4138272685

------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name          | Starts | E-Rows |E-Bytes| Cost (%CPU)| A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |               |      1 |        |       |     2 (100)|      1 |00:00:00.01 |       4 |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| TEST01        |      1 |      1 |    30 |     2   (0)|      1 |00:00:00.01 |       4 |
|*  2 |   INDEX RANGE SCAN                  | TEST01_IDX_ID |      1 |      1 |       |     1   (0)|      1 |00:00:00.01 |       3 |
------------------------------------------------------------------------------------------------------------------------------------

Wait for next Auto STS Capture Task schedule and check if the SQL_ID is in with both executions.

For me the manual execution does not add the 2-end plan to ASTS.

select SQLSET_NAME,PLAN_HASH_VALUE,PARSING_SCHEMA_NAME,BUFFER_GETS from DBA_SQLSET_STATEMENTS where SQL_ID='28stunrv2985c';

SQLSET_NAME                    PLAN_HASH_VALUE PARSING_SCHEMA_NAME            BUFFER_GETS
------------------------------ --------------- ------------------------------ -----------
SYS_AUTO_STS                         262542483 RED                                    453
SYS_AUTO_STS                        4138272685 RED                                    203