Sunday, May 3, 2026

AWR Analysis



Yes. Use one common STS loaded from all three AWR windows, then run one SQL Tuning Advisor task per SQL_ID. Do not run one giant Advisor task for all SQLs together; it will likely time out and become hard to interpret.

Also, important correction from your screenshot: remove this condition:

OR s.elapsed_time_delta > 0

That will pull almost every SQL from those AWR windows. For STS, keep the filter only on your watchlist SQL IDs.

Below script excludes 9kfty957z5y3 because you marked it NOT NEEDED. Add it back if required.


1. Create one STS for all selected SQL IDs

SET SERVEROUTPUT ON SIZE UNLIMITED

DECLARE
    l_sts_name VARCHAR2(30) := 'STS_JOB_WATCH_AWR';
BEGIN
    BEGIN
        DBMS_SQLTUNE.DROP_SQLSET(
            sqlset_name  => l_sts_name,
            sqlset_owner => USER
        );
    EXCEPTION
        WHEN OTHERS THEN
            NULL;
    END;

    DBMS_SQLTUNE.CREATE_SQLSET(
        sqlset_name => l_sts_name,
        description => 'Watchlist SQLs from BAD1, BAD2, and GOOD AWR windows'
    );

    DBMS_OUTPUT.PUT_LINE('Created STS: ' || l_sts_name);
END;
/

2. Load BAD1, BAD2, and GOOD windows into the STS

This loads all selected SQLs and all available plan hashes from those windows.

SET SERVEROUTPUT ON SIZE UNLIMITED

DECLARE
    l_cursor   DBMS_SQLTUNE.SQLSET_CURSOR;
    l_sts_name VARCHAR2(30) := 'STS_JOB_WATCH_AWR';

    l_filter VARCHAR2(4000) :=
        q'[sql_id IN (
              '1mufpt4a9awyx',
              'f2y77p2gtdg41',
              '7r1gn0tpbwjjj',
              'fsgs2mtg3tfpx',
              '6wa1frsf52nsy'
           )]';

    PROCEDURE load_window(
        p_label      IN VARCHAR2,
        p_begin_snap IN NUMBER,
        p_end_snap   IN NUMBER
    )
    IS
    BEGIN
        DBMS_OUTPUT.PUT_LINE('Loading ' || p_label || ' snaps ' || p_begin_snap || ' to ' || p_end_snap);

        OPEN l_cursor FOR
            SELECT VALUE(p)
            FROM   TABLE(
                       DBMS_SQLTUNE.SELECT_WORKLOAD_REPOSITORY(
                           begin_snap       => p_begin_snap,
                           end_snap         => p_end_snap,
                           basic_filter     => l_filter,
                           ranking_measure1 => 'elapsed_time',
                           result_limit     => 100,
                           attribute_list   => 'ALL',
                           dbid             => 352148541
                       )
                   ) p;

        DBMS_SQLTUNE.LOAD_SQLSET(
            sqlset_name     => l_sts_name,
            populate_cursor => l_cursor,
            load_option     => 'MERGE'
        );

        DBMS_OUTPUT.PUT_LINE('Loaded ' || p_label);
    END;
BEGIN
    load_window('BAD1_APR6_23_TO_APR7_03', 49153, 49160);
    load_window('BAD2_APR7_15_TO_21',      49184, 49196);
    load_window('GOOD_APR8_00_TO_01',      49202, 49204);

    DBMS_OUTPUT.PUT_LINE('Completed STS load: ' || l_sts_name);
END;
/

3. Validate what loaded into the STS

SET LINES 240
SET PAGES 200

COLUMN sqlset_name FORMAT A25
COLUMN sql_id FORMAT A15
COLUMN sql_text_sample FORMAT A90

SELECT sqlset_name,
       sql_id,
       plan_hash_value,
       SUM(executions) AS executions,
       ROUND(SUM(elapsed_time)/1e6, 2) AS elapsed_sec,
       ROUND(SUM(cpu_time)/1e6, 2) AS cpu_sec,
       SUM(buffer_gets) AS buffer_gets,
       SUM(disk_reads) AS disk_reads,
       SUBSTR(MAX(sql_text), 1, 90) AS sql_text_sample
FROM   dba_sqlset_statements
WHERE  sqlset_name = 'STS_JOB_WATCH_AWR'
GROUP BY sqlset_name,
         sql_id,
         plan_hash_value
ORDER BY sql_id,
         elapsed_sec DESC;

For 7r1gn0tpbwjjj, you should see both:

2340129260  -- bad plan
3257229599  -- good/recommended plan

4. Create SQL Tuning Advisor tasks for each SQL_ID

This creates one Advisor task per SQL. It does not execute yet.

SET SERVEROUTPUT ON SIZE UNLIMITED

DECLARE
    l_task_name VARCHAR2(128);
BEGIN
    FOR r IN (
        SELECT DISTINCT sql_id
        FROM   dba_sqlset_statements
        WHERE  sqlset_name = 'STS_JOB_WATCH_AWR'
        ORDER BY sql_id
    )
    LOOP
        l_task_name := 'STA_' || UPPER(r.sql_id) || '_AWR';

        BEGIN
            DBMS_SQLTUNE.DROP_TUNING_TASK(task_name => l_task_name);
        EXCEPTION
            WHEN OTHERS THEN
                NULL;
        END;

        l_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(
                           sqlset_name  => 'STS_JOB_WATCH_AWR',
                           sqlset_owner => USER,
                           basic_filter => 'sql_id = ''' || r.sql_id || '''',
                           scope        => DBMS_SQLTUNE.SCOPE_COMPREHENSIVE,
                           time_limit   => 7200,
                           task_name    => l_task_name,
                           description  => 'SQL Tuning Advisor from AWR STS for SQL_ID ' || r.sql_id
                       );

        DBMS_OUTPUT.PUT_LINE('Created task: ' || l_task_name);
    END LOOP;
END;
/

5. Execute the Advisor tasks one by one

Do not execute everything blindly if you are short on time. Start with the most important SQLs.

Execute only the critical SQL first

BEGIN
    DBMS_SQLTUNE.EXECUTE_TUNING_TASK(
        task_name => 'STA_7R1GN0TPBWJJJ_AWR'
    );
END;
/

Then run the others one at a time

BEGIN
    DBMS_SQLTUNE.EXECUTE_TUNING_TASK(task_name => 'STA_1MUFPT4A9AWYX_AWR');
END;
/

BEGIN
    DBMS_SQLTUNE.EXECUTE_TUNING_TASK(task_name => 'STA_F2Y77P2GTDG41_AWR');
END;
/

BEGIN
    DBMS_SQLTUNE.EXECUTE_TUNING_TASK(task_name => 'STA_FSGS2MTG3TFPX_AWR');
END;
/

BEGIN
    DBMS_SQLTUNE.EXECUTE_TUNING_TASK(task_name => 'STA_6WA1FRSF52NSY_AWR');
END;
/

If you want to include 9kfty957z5y3, create a separate task for it after adding it into the STS filter.


6. Check Advisor task status

SET LINES 240
SET PAGES 200

COLUMN task_name FORMAT A35
COLUMN status FORMAT A15
COLUMN execution_start FORMAT A30
COLUMN execution_end FORMAT A30
COLUMN status_message FORMAT A100

SELECT task_name,
       status,
       execution_start,
       execution_end,
       status_message
FROM   dba_advisor_log
WHERE  task_name LIKE 'STA_%_AWR'
ORDER BY execution_start DESC;

7. Generate Advisor report for each SQL

Example for 7r1gn0tpbwjjj:

SET LONG 10000000
SET LONGCHUNKSIZE 10000000
SET LINES 240
SET PAGES 0

SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK(
           task_name => 'STA_7R1GN0TPBWJJJ_AWR',
           type      => 'TEXT',
           level     => 'ALL'
       ) AS report
FROM dual;

For all reports, change the task name:

STA_1MUFPT4A9AWYX_AWR
STA_F2Y77P2GTDG41_AWR
STA_7R1GN0TPBWJJJ_AWR
STA_FSGS2MTG3TFPX_AWR
STA_6WA1FRSF52NSY_AWR

8. Pull high-level Advisor findings for all tasks

SET LINES 240
SET PAGES 200

COLUMN task_name FORMAT A35
COLUMN status FORMAT A15
COLUMN finding_name FORMAT A55
COLUMN rec_type FORMAT A35
COLUMN benefit FORMAT 999999999999
COLUMN command FORMAT A120

SELECT t.task_name,
       t.status,
       f.finding_name,
       r.type AS rec_type,
       r.benefit,
       SUBSTR(a.command, 1, 120) AS command
FROM   dba_advisor_tasks t
LEFT JOIN dba_advisor_findings f
       ON f.task_id = t.task_id
LEFT JOIN dba_advisor_recommendations r
       ON r.task_id = t.task_id
      AND r.finding_id = f.finding_id
LEFT JOIN dba_advisor_actions a
       ON a.task_id = t.task_id
      AND a.rec_id  = r.rec_id
WHERE  t.task_name LIKE 'STA_%_AWR'
ORDER BY t.task_name,
         r.benefit DESC;

9. For tomorrow, do not wait for all Advisor tasks

For immediate production protection, prioritize:

1. SQL_ID 7r1gn0tpbwjjj
   Good plan hash: 3257229599
   Bad plan hash : 2340129260

2. SQL_ID 1mufpt4a9awyx
   High reads/gets and AppFirewallCore impact

3. SQL_ID f2y77p2gtdg41
   Very high elapsed time

4. SQL_ID fsgs2mtg3tfpx
   Repeated long elapsed SQL

5. SQL_ID 6wa1frsf52nsy
   High CPU in good window

For 7r1gn0tpbwjjj, Advisor already confirmed the best action: create SQL Plan Baseline for plan hash 3257229599 and control PX/concurrency. The STS/Advisor work for the other SQLs is for deeper tuning, not tomorrow’s first-line protection.

------------------------------------------------------

 This result is expected for a heavy historical AWR SQL. The task did execute, but SQL Tuning Advisor timed out:

Completion Status : INTERRUPTED
Error             : ORA-13639: The current operation was interrupted because it timed out
Number of SQLs with Timeouts : 1

This is not an Oracle outage/error. It means the advisor could not finish deep analysis within your 1500 seconds.

For tomorrow’s job, do not wait on SQL Tuning Advisor as the primary fix. You already found the immediate control point:

Bad plan hash : 2340129260
Good plan hash: 3257229599
Risk driver   : PX / DOP / session explosion

So the immediate fix remains:

1. Load fixed baseline for good plan hash 3257229599.
2. Control/disable parallelism for this SQL/job.
3. Reduce job concurrency.
4. Monitor PX sessions live.

SQL Tuning Advisor can continue in parallel, but it is not the outage-prevention mechanism for tomorrow.


1. First check whether Advisor produced partial findings

Even with timeout, sometimes Oracle still captures useful findings.

SET LINES 240
SET PAGES 200

COLUMN task_name FORMAT A35
COLUMN status FORMAT A15
COLUMN finding_name FORMAT A50
COLUMN type FORMAT A30
COLUMN benefit FORMAT 999999999999
COLUMN command FORMAT A120

SELECT t.task_name,
       t.status,
       f.finding_name,
       r.type,
       r.benefit,
       SUBSTR(a.command, 1, 120) AS command
FROM   dba_advisor_tasks t
LEFT JOIN dba_advisor_findings f
       ON f.task_id = t.task_id
LEFT JOIN dba_advisor_recommendations r
       ON r.task_id = t.task_id
      AND r.finding_id = f.finding_id
LEFT JOIN dba_advisor_actions a
       ON a.task_id = t.task_id
      AND a.rec_id  = r.rec_id
WHERE  t.task_name = 'STA_7R1GN_BAD1_STS'
ORDER BY r.benefit DESC;

Also check the task log:

SET LINES 240
SET PAGES 200

COLUMN task_name FORMAT A35
COLUMN status FORMAT A20
COLUMN status_message FORMAT A100

SELECT task_name,
       status,
       execution_start,
       execution_end,
       status_message
FROM   dba_advisor_log
WHERE  task_name = 'STA_7R1GN_BAD1_STS'
ORDER BY execution_start DESC;

2. Re-run Advisor with higher time limit

Since the 25-minute run timed out, create a clean second task with a higher limit. For this SQL, I would use 2 hours if running off-window.

SET SERVEROUTPUT ON SIZE UNLIMITED

DECLARE
    l_task_name VARCHAR2(128);
BEGIN
    l_task_name := 'STA_7R1GN_BAD1_STS_2H';

    BEGIN
        DBMS_SQLTUNE.DROP_TUNING_TASK(task_name => l_task_name);
    EXCEPTION
        WHEN OTHERS THEN
            NULL;
    END;

    l_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(
                       sqlset_name  => 'STS_7R1GN_BAD1',
                       sqlset_owner => 'RDSADM',
                       basic_filter => q'[sql_id = '7r1gn0tpbwjjj' and plan_hash_value = 2340129260]',
                       scope        => DBMS_SQLTUNE.SCOPE_COMPREHENSIVE,
                       time_limit   => 7200,
                       task_name    => 'STA_7R1GN_BAD1_STS_2H',
                       description  => '2-hour SQL Tuning Advisor for bad plan 2340129260'
                   );

    DBMS_SQLTUNE.EXECUTE_TUNING_TASK(task_name => l_task_name);

    DBMS_OUTPUT.PUT_LINE('Executed task: ' || l_task_name);
END;
/

Report:

SET LONG 10000000
SET LONGCHUNKSIZE 10000000
SET LINES 240
SET PAGES 0

SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK(
           task_name => 'STA_7R1GN_BAD1_STS_2H',
           type      => 'TEXT',
           level     => 'ALL'
       ) AS report
FROM dual;

3. Quick Advisor run for tomorrow readiness

For a fast pre-check, run limited scope. This will not do the full deep SQL Profile analysis, but it can quickly catch stats/index/access-path recommendations.

SET SERVEROUTPUT ON SIZE UNLIMITED

DECLARE
    l_task_name VARCHAR2(128);
BEGIN
    l_task_name := 'STA_7R1GN_BAD1_LIMITED';

    BEGIN
        DBMS_SQLTUNE.DROP_TUNING_TASK(task_name => l_task_name);
    EXCEPTION
        WHEN OTHERS THEN
            NULL;
    END;

    l_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(
                       sqlset_name  => 'STS_7R1GN_BAD1',
                       sqlset_owner => 'RDSADM',
                       basic_filter => q'[sql_id = '7r1gn0tpbwjjj' and plan_hash_value = 2340129260]',
                       scope        => DBMS_SQLTUNE.SCOPE_LIMITED,
                       time_limit   => 600,
                       task_name    => 'STA_7R1GN_BAD1_LIMITED',
                       description  => 'Quick limited SQL Tuning Advisor for 7r1gn0tpbwjjj'
                   );

    DBMS_SQLTUNE.EXECUTE_TUNING_TASK(task_name => l_task_name);

    DBMS_OUTPUT.PUT_LINE('Executed task: ' || l_task_name);
END;
/

Report:

SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK(
           task_name => 'STA_7R1GN_BAD1_LIMITED',
           type      => 'TEXT',
           level     => 'ALL'
       ) AS report
FROM dual;

4. Do not make tomorrow dependent on Advisor

For tomorrow, the hard control should be this:

-- Good historical plan hash
3257229599

-- Bad historical plan hash
2340129260

Load the good plan as fixed baseline:

SET SERVEROUTPUT ON SIZE UNLIMITED

DECLARE
    l_loaded PLS_INTEGER;
BEGIN
    l_loaded := DBMS_SPM.LOAD_PLANS_FROM_AWR(
                    begin_snap   => 49184,
                    end_snap     => 49196,
                    basic_filter => q'[sql_id = '7r1gn0tpbwjjj' and plan_hash_value = 3257229599]',
                    fixed        => 'YES',
                    enabled      => 'YES'
                );

    DBMS_OUTPUT.PUT_LINE('Plans loaded: ' || l_loaded);
END;
/

Then verify live tomorrow:

SET LINES 240
SET PAGES 200

COLUMN sql_profile FORMAT A40
COLUMN sql_patch FORMAT A40
COLUMN sql_plan_baseline FORMAT A40
COLUMN module FORMAT A45

SELECT inst_id,
       sql_id,
       child_number,
       plan_hash_value,
       sql_profile,
       sql_patch,
       sql_plan_baseline,
       module,
       executions,
       elapsed_time/1000000 AS elapsed_sec,
       cpu_time/1000000     AS cpu_sec,
       buffer_gets,
       disk_reads,
       px_servers_executions
FROM   gv$sql
WHERE  sql_id = '7r1gn0tpbwjjj'
ORDER BY inst_id, child_number;

Expected tomorrow:

plan_hash_value should be 3257229599
plan_hash_value should NOT be 2340129260
PX_SERVERS_EXECUTIONS should not explode

5. My recommendation now

Use this decision path:

For tomorrow outage prevention:
    Baseline good plan hash 3257229599.
    Cap/disable parallelism for this job SQL.
    Reduce job concurrency.

For root-cause tuning:
    Run SQL Tuning Advisor with 7200 seconds off-window.
    Review recommendations.
    Do not blindly accept new SQL Profile if it increases parallelism.

Meeting-ready wording:

SQL Tuning Advisor was executed successfully from the historical AWR SQL Tuning Set, but the comprehensive analysis timed out after 1500 seconds. That confirms this is a heavy SQL optimization case, but it does not block tomorrow’s mitigation. We already identified the actionable risk: bad plan hash 2340129260 and high PX usage. For tomorrow, we should stabilize with the good plan hash 3257229599, control parallelism/concurrency, and continue the extended Advisor run off-window for permanent tuning recommendations.