Oracle 11g's SQL Performance Analyzer

A lot of things have already been said about the Real Application Testing Option -- from the price to the most interesting technical details -- by Ken Jacobs, Arup Nanda, and
even by me. Why add something? Because while Database Replay gets most people's attention, Real Application Testing offers another interesting feature called
SQL Performance Analyzer (SQLPA). So what is it? The DBMS_SQLPA package enables you to register and compare the statistics of several SQL query executions stored in an SQL Tuning Set (STS). With SQL Performance Analyzer, you can compare the executions of queries before and after you make some changes to your database. As you might guess, I'm going to illustrate this new feature in Oracle 11g with a simple example.
1. Create a sample table and its data You'll need to create a table and add a couple of rows for what comes next. The script below does this:
create table gark (id number not null); begin for i in 1..10000 loop insert into gark(id) values (i); end loop; commit; end; /2. Run a query and look at its plan The query below demonstrates the point. Run it from the SQL*Plus command line:
set serveroutput off col id format 99999 select a.id, b.id from gark a, gark b where a.id=b.id and b.id=500; select * from table( dbms_xplan.display_cursor);Here is the plan. Keep the SQL ID to add to the query in the SQL Tuning Set in the next section:
------------------------------------- SQL_ID 683kdkrs2dmrk, child number 0 ------------------------------------- select a.id, b.id from gark a, gark b where a.id=b.id and b.id=500 Plan hash value: 2625395012 ---------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| ---------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 15 (100)| |* 1 | HASH JOIN | | 1 | 26 | 15 (7)| |* 2 | TABLE ACCESS FULL| GARK | 1 | 13 | 7 (0)| |* 3 | TABLE ACCESS FULL| GARK | 1 | 13 | 7 (0)| ---------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("A"."ID"="B"."ID") 2 - filter("A"."ID"=500) 3 - filter("B"."ID"=500) Note ----- - dynamic sampling used for this statement3. Capture the query in an SQL Tuning Set Once the query is in the Shared Pool, you can create a new SQL Tuning Set and add the query to it:
- Firstly, create a new STS:
BEGIN DBMS_SQLTUNE.CREATE_SQLSET( sqlset_name => 'gark_sts', description => 'STS for SPA demo'); END; /
- Secondly, add the query to the STS by querying the Cursor Cache:
accept sql_id prompt "Enter value for sql_id: " 683kdkrs2dmrk DECLARE l_cursor DBMS_SQLTUNE.sqlset_cursor; BEGIN OPEN l_cursor FOR SELECT VALUE(p) FROM TABLE ( DBMS_SQLTUNE.select_cursor_cache ( 'sql_id = ''&sql_id''', -- basic_filter NULL, -- object_filter NULL, -- ranking_measure1 NULL, -- ranking_measure2 NULL, -- ranking_measure3 NULL, -- result_percentage 1) -- result_limit ) p; DBMS_SQLTUNE.load_sqlset ( sqlset_name => 'gark_sts', populate_cursor => l_cursor); END; / PL/SQL procedure successfully completed.
- Finally, you can query the STS content to make sure it is properly registered:
col sql format a50 set lines 120 SELECT sql_id, substr(sql_text, 1, 50) sql FROM TABLE( DBMS_SQLTUNE.select_sqlset ( 'gark_sts')); SQL_ID SQL ------------- --------------------- 683kdkrs2dmrk select a.id, b.id from gark a, gark b where a.i
- Create a SQLPA analysis task that reference the STS:
var v_out char(50) begin :v_out:=dbms_sqlpa.create_analysis_task( sqlset_name => 'gark_sts', task_name => 'gark_spa_task'); end; / print v_out V_OUT ------------- gark_spa_task
- Check the task has been created:
col TASK_NAME format a14 col ADVISOR_NAME format a24 select TASK_NAME, ADVISOR_NAME, created from DBA_ADVISOR_TASKS where task_name='gark_spa_task'; TASK_NAME ADVISOR_NAME CREATED -------------- ------------------------ --------- gark_spa_task SQL Performance Analyzer 15-AUG-07
- Run the SQLPA Analysis Task:
begin DBMS_SQLPA.EXECUTE_ANALYSIS_TASK( task_name => 'gark_spa_task', execution_type => 'TEST EXECUTE', execution_name => 'gark_spa_task_before'); end; /
- Monitor the task and its status until it is completed:
col TASK_NAME format a20 select execution_name, status, execution_end from DBA_ADVISOR_EXECUTIONS where task_name='gark_spa_task' order by execution_end; EXECUTION_NAME STATUS EXECUTION ------------------------------ ----------- --------- gark_spa_task_before COMPLETED 15-AUG-075. Perform the changes. I'm not very proud of this change, but lets create an index on the GARK table.
create unique index gark_idx on gark(id); Index created.6. Run the SQLPA analysis task after the changes The script is similar from the previous run. You just have to change the name to differentiate execution statistics before and after the changes:
- Run the SQLPA Analysis Task:
begin DBMS_SQLPA.EXECUTE_ANALYSIS_TASK( task_name => 'gark_spa_task', execution_type => 'TEST EXECUTE', execution_name => 'gark_spa_task_after'); end; /
- Monitor the task and its status until it is completed:
col TASK_NAME format a20 select execution_name, status, execution_end from DBA_ADVISOR_EXECUTIONS where task_name='gark_spa_task' order by execution_end; EXECUTION_NAME STATUS EXECUTION ------------------------------ ----------- --------- gark_spa_task_before COMPLETED 15-AUG-07 gark_spa_task_after COMPLETED 15-AUG-077. Compare the execution changes due to your database changes You'll run the analysis task once again. This time the Analyzer will compare and store the result of this comparison:
begin DBMS_SQLPA.EXECUTE_ANALYSIS_TASK( task_name => 'gark_spa_task', execution_type => 'COMPARE PERFORMANCE', execution_name => 'gark_spa_task_compare', execution_params => dbms_advisor.arglist( 'comparison_metric', 'buffer_gets')); end; / PL/SQL procedure successfully completed.Once done, you can print a report of this analysis with the
REPORT_ANALYSIS_TASK
function as below:
variable rep CLOB; begin :rep := DBMS_SQLPA.REPORT_ANALYSIS_TASK( task_name=>'gark_spa_task', type=>'HTML', level=>'ALL', section=>'ALL'); end; / SET LONG 100000 set LONGCHUNKSIZE 100000 set LINESIZE 200 set head off set feedback off set echo off spool sts_changes.html PRINT :rep spool off set head onMy tests suggest that the
SECTION
parameter must contain
SUMMARY
or
ALL
and not
SECTION_ALL
as quoted in the DBMS_SQLPA documentation. You can then view the result of your report from SQL*Plus (text output) or from a web browser (HTML output):
You'll find the full demo report here.
8. Another way to display the comparison result: Instead of printing the report, you can query the result from the following views:DBA_ADVISOR_FINDINGS
DBA_ADVISOR_SQLPLANS
DBA_ADVISOR_SQLSTATS
begin dbms_sqlpa.reset_analysis_task(task_name=>'gark_spa_task'); end; / col TASK_NAME format a20 select execution_name, status, execution_end from DBA_ADVISOR_EXECUTIONS where task_name='gark_spa_task' order by execution_end; no rows selectedAs well as the task itself:
begin dbms_sqlpa.drop_analysis_task(task_name=>'gark_spa_task'); end; / col TASK_NAME format a14 col ADVISOR_NAME format a24 select TASK_NAME, ADVISOR_NAME, created from DBA_ADVISOR_TASKS where task_name='gark_spa_task'; no rows selectedNote that you can also:
- cancel a running analysis task with the
cancel_analysis_task
procedure - interrupt a running analysis task with the
interrupt_analysis_task
procedure - resume an interrupted analysis task with the
resume_analysis_task
procedure
drop table gark cascade constraints purge;10. Conclusion This demonstration is very basic, but running the task on a test database with hundreds or thousands of queries won't really be more complex -- it simply might take more time. SQL Performance Analyzer is very different from Database Replay. I'll let you draw your own conclusions about the pros and cons:
- You can easily capture the STS queries from AWR.
- You don't need to rebuild the test system (only the "SELECT" part of the INSERT/UPDATE/DELETE is executed).
- The queries in a STS are only a sample of a real application workload.
- Oracle 11g Performance Tuning Guide - 23.SQL Performance Analyzer
- Oracle 11g PL/SQL Types and Packages Reference - DBMS_SQLPA
- Oracle 11g Reference