Sunday, February 9, 2025

Forcing Sql plan using Sql Plan baseline for oracle database

 
I already had another blog for sql profile  however at times we have scenario where sql profile is not used  and  we still see sql plan flip .  In such case we have to  prefer creating sql plan baseline . 

There are nany articles online already on  sql baselines however i wanted to create my own 


The use of SQL plan baselines is controlled by the OPTIMIZER_USE_SQL_PLAN_BASELINES parameter, which is set to TRUE by default. Access to the DBMS_SPM package requires the ADMINISTER SQL MANAGEMENT OBJECT privilege.



Creating Sql plan   baseline using  Sql   tuning sets :


=>  Drop   existing baseline for same sqlid if any 

BEGIN
   DBMS_SQLTUNE.DROP_SQLSET (sqlset_name => 'STS_f9948h4y2aa22');
END;
/


==>  Create new sql plan  baseline : 

BEGIN
  DBMS_SQLTUNE.CREATE_SQLSET(
    sqlset_name => 'STS_f9948h4y2aa22',
    description => 'SQL Tuning Set for loading plan into SQL Plan Baseline');
END;
/
 

==> Load all  plan details in sts :    


DECLARE
  cur sys_refcursor;
BEGIN
  OPEN cur FOR
    SELECT VALUE(P)
    FROM TABLE(
       dbms_sqltune.select_workload_repository(begin_snap=>6450, end_snap=>6451,basic_filter=>'sql_id = ''f9948h4y2aa22''',attribute_list=>'ALL')
              ) p;
     DBMS_SQLTUNE.LOAD_SQLSET( sqlset_name=> 'STS_f9948h4y2aa22', populate_cursor=>cur);
  CLOSE cur;
END;
/



-- if only current plan needs to be uploaded we can use cursor 

DECLARE
  cursor1 DBMS_SQLTUNE.SQLSET_CURSOR;
BEGIN
  OPEN cursor1 FOR SELECT VALUE(p)
  FROM TABLE(DBMS_SQLTUNE.SELECT_CURSOR_CACHE('sql_id = ''94rn6s4ba24wn''')) p;
 
  DBMS_SQLTUNE.LOAD_SQLSET(sqlset_name => 'STS01', populate_cursor => cursor1);
END;
/




 ==>   Check the loaded Plan details.

SELECT
  first_load_time          ,
  executions as execs              ,
  parsing_schema_name      ,
  elapsed_time  / 1000000 as elapsed_time_secs  ,
  cpu_time / 1000000 as cpu_time_secs           ,
  buffer_gets              ,
  disk_reads               ,
  direct_writes            ,
  rows_processed           ,
  fetches                  ,
  optimizer_cost           ,
  sql_plan                ,
  plan_hash_value          ,
  sql_id                   ,
  sql_text
   FROM TABLE(DBMS_SQLTUNE.SELECT_SQLSET(sqlset_name => 'STS_f9948h4y2aa22')
             );




==>  Load Good SQL Plan from STS   to  Baseline 

DECLARE
my_plans pls_integer;
BEGIN
  my_plans := DBMS_SPM.LOAD_PLANS_FROM_SQLSET(
    sqlset_name => 'STS_f9948h4y2aa22', 
    basic_filter=>'plan_hash_value = ''3166698470'''
    );
END;
/

Or 

Set serveroutput on;
DECLARE
my_plans PLS_INTEGER;
BEGIN
my_plans := DBMS_SPM.LOAD_PLANS_FROM_SQLSET( sqlset_name => 'BI_LOAD',sqlset_owner=>'PAYER1',basic_filter=>'sql_id='||CHR(39)||'08tz4k2shvbrr'||CHR(39)||' and plan_hash_value=2073609144',fixed=>'YES',enabled=>'YES');
dbms_output.put_line(my_plans);
END;
/





 Select sql_handle, sql_text, plan_name, accepted, enabled, fixed, reproduced, executions
FROM dba_sql_plan_baselines;



Using DBMS_SPM.ALTER_SQL_PLAN_BASELINE disable the bad plan :

SQL> variable cnt number;
SQL> exec :cnt :=DBMS_SPM.ALTER_SQL_PLAN_BASELINE(SQL_HANDLE => 'SYS_SQL_bf5c9b08f72bde3e',PLAN_NAME=> 'SQL_PLAN_byr4v13vkrrjy42949306',
ATTRIBUTE_NAME => 'enabled',ATTRIBUTE_VALUE => 'NO');




set linesize 125
col sql_id         format a14
col sql_handle     format a22
col plan_name      format a32
col sql_text       format a40
col enabled        format a8
col accepted       format a8
SELECT
               dbms_sql_translator.sql_id(sql_text) AS sql_id,
               sql_handle                                    ,
               plan_name                                     ,
               enabled                                       ,
               accepted                                      ,
               reproduced                                    ,
               fixed
          FROM
               dba_sql_plan_baselines
         WHERE
               dbms_sql_translator.sql_id(sql_text) = '3wwhfmb2ztb40';




==>   Drop baseline when done 

set serveroutput on;
DECLARE
my_plans PLS_INTEGER;
BEGIN
my_plans :=DBMS_SPM.DROP_SQL_PLAN_BASELINE (plan_name=>'SQL_PLAN_fn4qykbuqnt9bcf84f431');
dbms_output.put_line(my_plans);
END;
/





Other Ways to force sql plan without STS as per Doc ID 2885167.1


variable x number
BEGIN
:x := dbms_spm.load_plans_from_awr(
begin_snap => 292,
end_snap => 294,
basic_filter => q'# sql_id='3wwhfmb2ztb40' and plan_hash_value='3080277828' #');
END;
/
print x





Export Import  Baseline : 


Oracle Database supports the export and import of SQL plan baselines using its import and export utilities or Oracle Data Pump. Use the DBMS_SPM package to define a staging table, which is then used to pack and unpack SQL plan baselines.

To import a set of SQL plan baselines from one system to another:

On the original system, create a staging table using the CREATE_STGTAB_BASELINE procedure:

BEGIN
  DBMS_SPM.CREATE_STGTAB_BASELINE(
    table_name => 'stage1');
END;
/
This example creates a staging table named stage1.

Pack the SQL plan baselines you want to export from the SQL management base into the staging table using the PACK_STGTAB_BASELINE function:

DECLARE
my_plans number;
BEGIN
  my_plans := DBMS_SPM.PACK_STGTAB_BASELINE(
    table_name => 'stage1',
    enabled => 'yes',
    creator => 'dba1');
END;
/
This example packs all enabled plan baselines created by user dba1 into the staging table stage1. You can select SQL plan baselines using the plan name (plan_name), SQL handle (sql_handle), or by any other plan criteria. The table_name parameter is mandatory.

Export the staging table stage1 into a flat file using the export command or Oracle Data Pump.

Transfer the flat file to the target system.

Import the staging table stage1 from the flat file using the import command or Oracle Data Pump.

Unpack the SQL plan baselines from the staging table into the SQL management base on the target system using the UNPACK_STGTAB_BASELINE function:

DECLARE
my_plans number;
BEGIN
  my_plans := DBMS_SPM.UNPACK_STGTAB_BASELINE(
    table_name => 'stage1',
    fixed => 'yes');
END;
/
This example unpacks all fixed plan baselines stored in the staging table stage1.





Export Import STS ( Sql tuning Sets ) :

Transferring SQL Tuning Sets

In the examples listed above, the tests have been performed on the same system. In reality you are more likely to want to create a tuning set on your production system, then run the SQL Performance Analyzer against it on a test system. Fortunately, the DBMS_SQLTUNE package allows you to transport SQL tuning sets by storing them in a staging table.

First, create the staging table using the CREATE_STGTAB_SQLSET procedure.

CONN sys/password@prod AS SYSDBA

BEGIN
  DBMS_SQLTUNE.create_stgtab_sqlset(table_name      => 'SQLSET_TAB',
                                    schema_name     => 'SPA_TEST_USER',
                                    tablespace_name => 'USERS');
END;
/
Next, use the PACK_STGTAB_SQLSET procedure to export SQL tuning set into the staging table.

BEGIN
  DBMS_SQLTUNE.pack_stgtab_sqlset(sqlset_name          => 'SPA_TEST_SQLSET',
                                  sqlset_owner         => 'SYS',
                                  staging_table_name   => 'SQLSET_TAB',
                                  staging_schema_owner => 'SPA_TEST_USER');
END;
/
Once the SQL tuning set is packed into the staging table, the table can be transferred to the test system using Datapump, Export/Import or via a database link. Once on the test system, the SQL tuning set can be imported using the UNPACK_STGTAB_SQLSET procedure.

BEGIN
  DBMS_SQLTUNE.unpack_stgtab_sqlset(sqlset_name          => '%',
                                    sqlset_owner         => 'SYS',
                                    replace              => TRUE,
                                    staging_table_name   => 'SQLSET_TAB',
                                    staging_schema_owner => 'SPA_TEST_USER');
END;
/
The SQL tuning set can now be used with the SQL Performance Analyzer on the test system.






Reference :

How to Create A SQL Plan Baseline From A Historical Execution Plan In The Automatic Workload Repository (AWR) [RDBMS Version 12.2 or Higher] (Doc ID 2885167.1)

https://oracle-base.com/articles/11g/sql-plan-management-11gr1



No comments:

Post a Comment