Skip to main content

export/import query plan from one database to another using sql tuning set and sql plan baseline


The following three links are my guide documents:

https://carlos-sierra.net/2013/05/02/migrating-an-execution-plan-using-sql-plan-management/

https://aprakash.wordpress.com/2012/07/05/loading-sql-plan-into-spm-using-awr/

https://www.databasejournal.com/features/oracle/article.php/3730391/Oracle-Database-11g-SQL-Plan-Management-Part-2.htm

Option 1: Create SPB on source then migrate SPB into target

Steps:
  1. Create SQL Plan Baseline (SPB) in Source
    1. From Memory; or
    2. From AWR (requires Diagnostics Pack license)
  2. Package & Export SPB from Source
  3. Import & Restore SPB into Target
Pros: Simple
Cons: Generates a SPB in Source system

Option 2: Create SQL Tuning Set (STS) on source, migrate STS into target, promote STS into SPB in target

Steps:
  1. Create SQL Tuning Set (STS) in Source (requires Tuning Pack license)
    1. From Memory; or
    2. From AWR (requires Diagnostics Pack license)
  2. Package & Export STS from Source
  3. Import & Restore STS into Target
  4. Create SPB from STS in Target
Pros: No SPB is created in Source system
Cons: Requires license for SQL Tuning Pack
Below are the steps I implement option 2:
exec DBMS_SQLTUNE.DROP_SQLSET(sqlset_name => 'jsun_sqlset'    );
exec dbms_sqltune.create_sqlset(sqlset_name => 'jsun_sqlset',description => 'sqlset descriptions');

/*
DBMS_SQLTUNE.CAPTURE_CURSOR_CACHE_SQLSET(                         
         sqlset_name => 'STS_SPM_200'
        ,basic_filter=> q'#sql_text LIKE '%SPM_2_1%' AND parsing_schema_name = 'LDGN'#'
        ,time_limit  => 300
        ,repeat_interval => 5
    ); 
*/    
--Here we would be see how to manually load the plans from AWR to SQL Plan Baseline.To load from AWR we need to create sql tuning set
--Identify the snap_id in which the sql belongs using dba_hist_sqlstat view.Once identified

--select distinct sql_id from v$sql_plan where plan_hash_value='&plan_hash_value'
select min(SNAP_ID),max(SNAP_ID) from DBA_HIST_SQLSTAT where sql_id='&sqlid' or plan_hash_value='&plan_hash_value';

declare
baseline_ref_cur DBMS_SQLTUNE.SQLSET_CURSOR;
begin
open baseline_ref_cur for
select VALUE(p) from table(
DBMS_SQLTUNE.SELECT_WORKLOAD_REPOSITORY(&begin_snap_id, &end_snap_id,'sql_id='||CHR(39)||'&sql_id'||CHR(39)||'',NULL,NULL,NULL,NULL,NULL,NULL,'ALL')) p;
DBMS_SQLTUNE.LOAD_SQLSET('jsun_sqlset', baseline_ref_cur);
end;
/

--It would prompt for the begin_snapid , end_snapid and the sql_id for which you want to load the sqlset with. Along with sql_id we can give the specific plan_hash_value in DBMS_SQLTUNE.SELECT_WORKLOAD_REPOSITORY.
--By default, select_workload_repository does not include the SQL Plan so we pass TYPICAL or ALL as the ‘attribute_list’ parameter to get the plan. The default value of BASIC does not capture the plan.
/*
declare
baseline_ref_cur DBMS_SQLTUNE.SQLSET_CURSOR;
begin
open baseline_ref_cur for
select VALUE(p) from table(
DBMS_SQLTUNE.SELECT_WORKLOAD_REPOSITORY(&begin_snap_id, &end_snap_id,'sql_id='||CHR(39)||'&sql_id'||CHR(39)||' and plan_hash_value=1421641795',NULL,NULL,NULL,NULL,NULL,NULL,'ALL')) p;
DBMS_SQLTUNE.LOAD_SQLSET('b8rc6j0krxwdc_sqlset_test', baseline_ref_cur);
end;
/
*/
--View the sqlset using DBA_SQLSET
SELECT NAME,OWNER,CREATED,STATEMENT_COUNT FROM DBA_SQLSET where name='jsun_sqlset';

--To verify the execution Plan of a SQL_ID in the STS
select * from table(dbms_xplan.display_sqlset('jsun_sqlset','&sql_id'));

--pack the STS
DROP TABLE jsun.sts_staging PURGE;
BEGIN
    DBMS_SQLTUNE.CREATE_STGTAB_SQLSET(
         table_name => 'STS_STAGING'
        ,schema_name => 'JSUN'
        ,tablespace_name => 'USERS'
    );
    DBMS_SQLTUNE.PACK_STGTAB_SQLSET(
         sqlset_name => 'jsun_sqlset'
        ,sqlset_owner => 'JSUN'
        ,staging_table_name => 'STS_STAGING'
        ,staging_schema_owner => 'JSUN'
    );
END;
/
--export the STS table
exp jsun file=saletrn10.dmp tables=jsun.STS_STAGING
--import the STS table
imp jsun file=saletrn10.dmp tables=STS_STAGING fromuser=jsun touser=jsun
--unpack the STS
BEGIN
    DBMS_SQLTUNE.DROP_SQLSET(
        sqlset_name => 'jsun_sqlset'
    );
END;
/
BEGIN
    DBMS_SQLTUNE.UNPACK_STGTAB_SQLSET(
         sqlset_name => 'jsun_sqlset'
        ,sqlset_owner => 'JSUN'
        ,replace => TRUE
        ,staging_table_name => 'STS_STAGING'
        ,staging_schema_owner => 'JSUN'
    );
END;
/
SELECT NAME,OWNER,CREATED,STATEMENT_COUNT FROM DBA_SQLSET where name='jsun_sqlset';

--To load SQL execution plans from SQL set into SQL baseline —
set serveroutput on
declare
my_int pls_integer;
begin
my_int := dbms_spm.load_plans_from_sqlset (
sqlset_name => 'jsun_sqlset',
basic_filter => 'sql_id='||chr(39)||'&sqlid'||chr(39),
sqlset_owner => 'JSUN',
fixed => 'NO',
enabled => 'YES');
DBMS_OUTPUT.PUT_line(my_int);
end;

select count(*) from dba_sql_plan_baselines;
SELECT SQL_HANDLE, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED, FIXED, MODULE FROM   DBA_SQL_PLAN_BASELINES;

--now run the query and see the plan has been ported.

set autotrace on
set timing on
--run query  



Comments

Popular posts from this blog

non-existent process lock port on windows server

I have a database link created between oracle and sqlserver using oracle tg4odbc, the product is installed on windows server and run as service "OracleOraGtw11g_home1TNSListener", but sometime the service cannot started, the root cause of this problem is that the port number 1521 is used by an non-existent process. The first step is to use netstat -bano|find "1521" to get the process id, in my case it's 5844, which shows the connection is from my oracle server 10.8.0.169 H:\>netstat -bano|find "1521"   TCP    0.0.0.0:1521           0.0.0.0:0              LISTENING       5844   TCP    10.14.45.33:1521       10.8.0.169:42987       ESTABLISHED     5844 however the process id does not show in either task manager or process explorer. The next step is to run tcpview, which shows non-existent under process column, there are three rows, two show status as "listening", the other one shows status "established", right click and k

Opatch apply/lsinventory error: oneoff is corrupted or does not exist

I am applying the quarterly patch for 19c RDBMS, I tried using napply but failed, but somehow it corrupted the inventory though nothing applied. further apply and lsinventory command ran into error like this: $ ./OPatch/opatch lsinventory Oracle Interim Patch Installer version 12.2.0.1.21 Copyright (c) 2020, Oracle Corporation.  All rights reserved. Oracle Home       : /u02/app/oracle/19.0.0 Central Inventory : /u01/app/oraInventory    from           : /u02/app/oracle/19.0.0/oraInst.loc OPatch version    : 12.2.0.1.21 OUI version       : 12.2.0.7.0 Log file location : /u02/app/oracle/19.0.0/cfgtoollogs/opatch/opatch2020-09-08_13-35-59PM_1.log Lsinventory Output file location : /u02/app/oracle/19.0.0/cfgtoollogs/opatch/lsinv/lsinventory2020-09-08_13-35-59PM.txt -------------------------------------------------------------------------------- Inventory load failed... OPatch cannot load inventory for the given Oracle Home. LsInventorySession failed: Unable to create patchObject Possible ca

shell script to clean up oracle dumpfile

https://github.com/iacosta/personal/blob/master/shells/cleanhouse.sh #!/bin/ksh # # Script used to cleanup any Oracle environment. # # Cleans:      audit_file_dest #              background_dump_dest #              core_dump_dest #              user_dump_dest #              Clusterware logs # # Rotates:     Alert Logs #              Listener Logs # # Scheduling:  00 00 * * * /networkdrive/dba/scripts/purge/cleanup.sh -d 7 > /u01/dba/bin/cleanup.log 2>&1 # # Created By:  Lei Dao # # # RM="rm -f" RMDIR="rm -rf" LS="ls -l" MV="mv" TOUCH="touch" TESTTOUCH="echo touch" TESTMV="echo mv" TESTRM=$LS TESTRMDIR=$LS SUCCESS=0 FAILURE=1 TEST=0 HOSTNAME=`hostname` ORAENV="oraenv" TODAY=`date +%Y%m%d` ORIGPATH=/usr/local/bin:$PATH ORIGLD=$LD_LIBRARY_PATH export PATH=$ORIGPATH # Usage function. f_usage(){   echo "Usage: `basename $0` -d DAYS [-a DAYS] [-b DAYS] [