Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Prithviraj.

Asked: January 30, 2018 - 12:25 pm UTC

Last updated: January 30, 2018 - 2:04 pm UTC

Version: 11.2

Viewed 1000+ times

You Asked

Is it possible to have multiple SQL Profiles for same query?

and Chris said...

Yes. Provided you create them in different categories!

create table t as 
  select level x, lpad('x', 100, 'x') y 
  from   dual
  connect by level <= 100;
  
set serveroutput off
select * from t where x = 1;

select * 
from   table(dbms_xplan.display_cursor(null, null, 'BASIC LAST +OUTLINE'));

PLAN_TABLE_OUTPUT                                  
EXPLAINED SQL STATEMENT:                           
------------------------                           
select * from t where x = 1                        
                                                   
Plan hash value: 2498539100                        
                                                   
----------------------------------                 
| Id  | Operation         | Name |                 
----------------------------------                 
|   0 | SELECT STATEMENT  |      |                 
|   1 |  TABLE ACCESS FULL| T    |                 
----------------------------------                 
                                                   
Outline Data                                       
-------------                                      
                                                   
  /*+                                              
      BEGIN_OUTLINE_DATA                           
      IGNORE_OPTIM_EMBEDDED_HINTS                  
      OPTIMIZER_FEATURES_ENABLE('12.2.0.1')        
      DB_VERSION('12.2.0.1')                       
      OPT_PARAM('_optimizer_cost_model' 'fixed')   
      OPT_PARAM('_fix_control' '6670551:0')        
      ALL_ROWS                                     
      OUTLINE_LEAF(@"SEL$1")                       
      FULL(@"SEL$1" "T"@"SEL$1")                   
      END_OUTLINE_DATA                             
  */

begin
  dbms_sqltune.import_sql_profile (
    sql_text => 'select * from t where x = 1',
    name     => 'ORIG_PROF',
    profile  => sqlprof_attr(q'|  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
      DB_VERSION('12.2.0.1')
      OPT_PARAM('_optimizer_cost_model' 'fixed')
      OPT_PARAM('_fix_control' '6670551:0')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      FULL(@"SEL$1" "T"@"SEL$1")
      END_OUTLINE_DATA
  */ |')
  );
end;
/

select * from dba_sql_profiles;

create index i on t(x);

set serveroutput off
select * from t where x = 1;

select * 
from   table(dbms_xplan.display_cursor(null, null, 'BASIC LAST +OUTLINE'));

PLAN_TABLE_OUTPUT                                         
EXPLAINED SQL STATEMENT:                                  
------------------------                                  
select * from t where x = 1                               
                                                          
Plan hash value: 3995057492                               
                                                          
----------------------------------------------------      
| Id  | Operation                           | Name |      
----------------------------------------------------      
|   0 | SELECT STATEMENT                    |      |      
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| T    |      
|   2 |   INDEX RANGE SCAN                  | I    |      
----------------------------------------------------      
                                                          
Outline Data                                              
-------------                                             
                                                          
  /*+                                                     
      BEGIN_OUTLINE_DATA                                  
      IGNORE_OPTIM_EMBEDDED_HINTS                         
      OPTIMIZER_FEATURES_ENABLE('12.2.0.1')               
      DB_VERSION('12.2.0.1')                              
      OPT_PARAM('_optimizer_cost_model' 'fixed')          
      OPT_PARAM('_fix_control' '6670551:0')               
      ALL_ROWS                                            
      OUTLINE_LEAF(@"SEL$1")                              
      INDEX_RS_ASC(@"SEL$1" "T"@"SEL$1" ("T"."X"))        
      BATCH_TABLE_ACCESS_BY_ROWID(@"SEL$1" "T"@"SEL$1")   
      END_OUTLINE_DATA                                    
  */  

begin
  dbms_sqltune.import_sql_profile (
    sql_text => 'select * from t where x = 1',
    name     => 'NEW_PROF',
    profile  => sqlprof_attr(q'|  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
      DB_VERSION('12.2.0.1')
      OPT_PARAM('_optimizer_cost_model' 'fixed')
      OPT_PARAM('_fix_control' '6670551:0')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX_RS_ASC(@"SEL$1" "T"@"SEL$1" ("T"."X"))
      BATCH_TABLE_ACCESS_BY_ROWID(@"SEL$1" "T"@"SEL$1")
      END_OUTLINE_DATA
  */ |')
  );
end;
/

ORA-13830: SQL profile or patch with category DEFAULT already exists for this SQL statement

begin
  dbms_sqltune.import_sql_profile (
    sql_text => 'select * from t where x = 1',
    name     => 'NEW_PROF',
    profile  => sqlprof_attr(q'|  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
      DB_VERSION('12.2.0.1')
      OPT_PARAM('_optimizer_cost_model' 'fixed')
      OPT_PARAM('_fix_control' '6670551:0')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX_RS_ASC(@"SEL$1" "T"@"SEL$1" ("T"."X"))
      BATCH_TABLE_ACCESS_BY_ROWID(@"SEL$1" "T"@"SEL$1")
      END_OUTLINE_DATA
  */ |'),
    category => 'TEST'
  );
end;
/

select name, category, sql_text
from   dba_sql_profiles;

NAME        CATEGORY   SQL_TEXT                      
NEW_PROF    TEST       select * from t where x = 1   
ORIG_PROF   DEFAULT    select * from t where x = 1 


This allows you to try out the new profile while leaving the existing one in place. You can do this by setting the sqltune_category parameter:

sho parameter sqltune_category

NAME             TYPE   VALUE   
---------------- ------ ------- 
sqltune_category string DEFAULT 

select * from t where x = 1;

select * 
from   table(dbms_xplan.display_cursor(null, null, 'BASIC LAST +NOTE'));

PLAN_TABLE_OUTPUT                                          
EXPLAINED SQL STATEMENT:                                   
------------------------                                   
select * from t where x = 1                                
                                                           
Plan hash value: 3995057492                                
                                                           
----------------------------------------------------       
| Id  | Operation                           | Name |       
----------------------------------------------------       
|   0 | SELECT STATEMENT                    |      |       
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| T    |       
|   2 |   INDEX RANGE SCAN                  | I    |       
----------------------------------------------------       
                                                           
Note                                                       
-----                                                      
   - dynamic statistics used: dynamic sampling (level=2)   
   - SQL profile ORIG_PROF used for this statement

alter session set sqltune_category = 'TEST';

select * from t where x = 1;

select * 
from   table(dbms_xplan.display_cursor(null, null, 'BASIC LAST +NOTE'));

PLAN_TABLE_OUTPUT                                          
EXPLAINED SQL STATEMENT:                                   
------------------------                                   
select * from t where x = 1                                
                                                           
Plan hash value: 3995057492                                
                                                           
----------------------------------------------------       
| Id  | Operation                           | Name |       
----------------------------------------------------       
|   0 | SELECT STATEMENT                    |      |       
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| T    |       
|   2 |   INDEX RANGE SCAN                  | I    |       
----------------------------------------------------       
                                                           
Note                                                       
-----                                                      
   - dynamic statistics used: dynamic sampling (level=2)   
   - SQL profile NEW_PROF used for this statement 


Is this answer out of date? If it is, please let us know via a Comment

More to Explore

Performance

Get all the information about database performance in the Database Performance guide.