(shipped with SQLT) (文档 ID 1400903.1)
APPLIES TO:
Oracle Database - Enterprise Edition - Version 10.1.0.2 and later
Information in this document applies to any platform.
GOAL
This document explains the steps necessary to use coe_load_sql_baseline.sql / coe_load_sql_profile.sql to apply a custom SQL Baseline (in 11g and higher) or a custom SQL Profile (in 10g and higher).
One application of this is to prompt the optimizer to use a plan that could only be achieved through adding hints. For example: When you cannot modify the original SQL for whatever reason and you would like to "capture" the plan from a modified version of your SQL (the one with CBO Hints) and associate this "good" plan to the original un-modified SQL.
NOTE: Care should be taken to ensure that the 2 queries are syntactically identical in order to obtain the desired result. If for example the aliases used or predicates in the query are different, the optimizer may not be able to follow the directives. In this case, the profile may be ignored by the optimizer or a different non-optimal plan obtained.
coe_load_sql_baseline.sql / coe_load_sql_profile.sql are scripts provided with the SQLT tool in the "utl" folder.
NOTE: Licensing considerations:
Both the coe_load_sql_baseline.sql and coe_load_sql_profile.sql scripts may require licenses depending on how they are used.
The coe_load_sql_profile.sql script calls DBMS_SQLTUNE (which is a Licensed Command-Line API) requiring the Tuning Pack license (for which Oracle Diagnostics Pack is a prerequisite).
If the coe_load_sql_baseline.sql script finds the required plans in memory then it does not require any license. However, if it retrieves plans from the Automatic Workload Repository (AWR), a Diagnostic Pack license would be required.
SQLT is a tool provided by Oracle Server Technologies Center of Expertise - ST CoE. SQLT inputs one SQL statement and outputs a set of diagnostics files that are commonly used to diagnose SQL statements performing poorly.You can download SQLT from:
Document: 215187.1 SQLT (SQLTXPLAIN) - Tool That Helps To Diagnose SQL Statements Performing Poorly
SOLUTION
There are many possible applications for the coe_load_sql_baseline.sql / coe_load_sql_profile.sql scripts. What follows is an example usage to prompt the optimizer to use a plan that could only be achieved through adding hints.
Instructions
- Make sure that both the original and modified statement are in memory. This can be achieved by executing the queries. Find the sql_id and plan_hash_value for both the original sql (without hints) and the modified sql (with hints)
- Decide whether you want to guarantee plan stability for the statement (baseline) or not (profile). To help you decide refer to the following:
Document 1524658.1 FAQ: SQL Plan Management (SPM) Frequently Asked Questions
- Change directory to sqlt/utl
Following 2 scripts in the sqlt/utl directory can be used to achieve the goal explained in this document:- coe_load_sql_baseline.sql (11g and higher)
Loads a plan from the modified sql with hints into a custom sql plan baseline of original SQL (without hints)
For more information on baselines and plan stability see:Document 1359841.1 Plan Stability Features (Including SPM) Start Point
- coe_load_sql_profile.sql (10g and higher)
Loads the plan from the modified sql with hints sql into a custom sql profile of the original SQL (without hints)
For more information on sql profiles see:Document 271196.1 Automatic SQL Tuning - SQL Profiles.
- coe_load_sql_baseline.sql (11g and higher)
- Run the script coe_load_sql_baseline.sql or coe_load_sql_profile.sql and provide the sql_id of the original statement and the sql_id and plan_hash_value of the modified sql statement.
Example
Setup:
SQL> -- For our example we will create an index on emp as follows:
SQL> create index i_emp_ename on scott.emp(ename);
Index created.
SQL> -- Gather statistics
SQL> exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'EMP')
PL/SQL procedure successfully completed.
Step 1: Run Original SQL
SQL>-- Run original SQL --
SQL> select ename from scott.emp where ename='MILLER';
Plan hash value: 3045807146 --------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| --------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 6 | 1 (0)| |* 1 | INDEX RANGE SCAN| I_EMP_ENAME | 1 | 6 | 1 (0)| ---------------------------------------------------------------------
This is the query for which we want to change the plan
Step 2: Run Hinted SQL
SQL>-- Run hinted SQL --
SQL> select /*+ FULL (EMP) */ ename from scott.emp where ename='MILLER';
Plan hash value: 2872589290 --------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| --------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 6 | 3 (0)| |* 1 | TABLE ACCESS FULL| EMP | 1 | 6 | 3 (0)| ---------------------------------------------------------------
This is the hinted query with the desired plan.
Step 3: Find sql_id and plan_hash_value for the 2 SQLs
SQL> select sql_id ,plan_hash_value, sql_text from v$sql where sql_text like '%scott.emp%';
SQL_ID PLAN_HASH_VALUE
------------- ---------------
SQL_TEXT
--------------------------------------------------------------------------------
0vdqhcj6gaqnt 3924418374
select sql_id ,plan_hash_value, sql_text from v$sql where sql_text like '%scott.
emp%'
4f74t4ab7rd5y 2872589290
select /*+ FULL (EMP) */ ename from scott.emp where ename='MILLER'
329d885bxvrcr 3045807146
select ename from scott.emp where ename='MILLER'
Original sql id: 329d885bxvrcr - this is the SQL ID of the original statement. We want to change the plan for this statement to that of the hinted SQL.
Modified sql id: 4f74t4ab7rd5y - this is the SQL ID of the hinted statement. This is the source of the plan for the statement we want to change.
Modified Plan Hash Value: 2872589290 - this is the PHV of the target plan (the plan from the hinted query)
Step 4
At this point there are 2 options to stabilize the plan.
A: If you want to force the access path, use an outline (coe_load_sql_baseline.sql)
B: If you want to push the plan in a particular direction but want some flexibility then use a profile (coe_load_sql_profile.sql)
A: Using coe_load_sql_baseline.sql
- The original SQL must be in cache or AWR
- The modified SQL must be in cache
- Connect as user with DBA privilege, for example SYSTEM
NOTES:
Do not connect as SYS as the staging table cannot be created in SYS schema and you will receive an error: ORA-19381: cannot create staging table in SYS schema
Licensing: If the coe_load_sql_baseline.sql script finds the required plans in memory then it does not require any license. However, if it retrieves plans from the Automatic Workload Repository (AWR), a Diagnostic Pack license would be required.
SQL> @coe_load_sql_baseline.sql Parameter 1: ORIGINAL_SQL_ID (required) Enter value for 1: 329d885bxvrcr Parameter 2: MODIFIED_SQL_ID (required) Enter value for 2: 4f74t4ab7rd5y PLAN_HASH_VALUE AVG_ET_SECS -------------------- -------------------- 2872589290 .003 Parameter 3: PLAN_HASH_VALUE (required) Enter value for 3: 2872589290 Values passed to coe_load_sql_baseline: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ORIGINAL_SQL_ID: "329d885bxvrcr" MODIFIED_SQL_ID: "4f74t4ab7rd5y" PLAN_HASH_VALUE: " 2872589290" . . . **************************************************************************** * Enter SCOTT password to export staging table STGTAB_BASELINE_329d885bxvrcr **************************************************************************** Export: Release 11.2.0.3.0 - Production on Sun Mar 11 15:08:56 2012 Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved. Password: . . . deleting: coe_load_sql_baseline.log coe_load_sql_baseline completed.
Run original query
SQL> select ename from scott.emp where ename='MILLER';
Plan hash value: 2872589290 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 6 | 3 (0)| 00:00:01 | |* 1 | TABLE ACCESS FULL| EMP | 1 | 6 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("ENAME"='MILLER') Note ----- - SQL plan baseline "329D885BXVRCR_4F74T4AB7RD5Y" used for this statement
We see that the original sql now has the same plan_hash_value as the hinted sql and the same plan.
Furthermore we see the a SQL plan baseline is enabled for this statement.
B: Using coe_load_sql_profile.sql
- Both plans need to be in cache or in AWR
- Connect as user with DBA privilege, for example SYSTEM
NOTES:
Do not connect as SYS as the staging table cannot be created in SYS schema and you will receive an error: ORA-19381: cannot create staging table in SYS schema
Licensing: The coe_load_sql_profile.sql script calls DBMS_SQLTUNE (which is a Licensed Command-Line API) requiring the Tuning Pack license (for which Oracle Diagnostics Pack is a prerequisite).
connect system/pass
SQL> @coe_load_sql_profile.sql Parameter 1: ORIGINAL_SQL_ID (required) Enter value for 1: 329d885bxvrcr Parameter 2: MODIFIED_SQL_ID (required) Enter value for 2: 4f74t4ab7rd5y PLAN_HASH_VALUE AVG_ET_SECS -------------------- -------------------- 2872589290 .003 Parameter 3: PLAN_HASH_VALUE (required) Enter value for 3: 2872589290 Values passed to coe_load_sql_profile: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ORIGINAL_SQL_ID: "329d885bxvrcr" MODIFIED_SQL_ID: "4f74t4ab7rd5y" PLAN_HASH_VALUE: "2872589290" . . . ORIGINAL:329D885BXVRCR MODIFIED:4F74T4AB7RD5Y PHV:2872589290 SIGNATURE:15822026218863957422 CREATED BY COE_LOAD_SQL_PROFILE.SQL SQL>SET ECHO OFF; **************************************************************************** * Enter SCOTT password to export staging table STGTAB_SQLPROF_329d885bxvrcr **************************************************************************** Export: Release 11.2.0.3.0 - Production on Sun Mar 11 14:45:47 2012 Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved. Password: . . . coe_load_sql_profile completed.
Run original query
SQL> select ename from scott.emp where ename='MILLER';
Plan hash value: 2872589290 --------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| --------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 6 | 3 (0)| |* 1 | TABLE ACCESS FULL| EMP | 1 | 6 | 3 (0)| --------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("ENAME"='MILLER') Note ----- - SQL profile "329D885BXVRCR_2872589290" used for this statement
We see that the original SQL now has the same plan_hash_value as the hinted sql and the same plan. Furthermore we see the a SQL profile is enabled for this statement