Skip to content

Commit c47743c

Browse files
authored
New SPM example (oracle-samples#152)
* security update * security update * security update * SPA helper example
1 parent 95c24aa commit c47743c

File tree

6 files changed

+299
-1
lines changed

6 files changed

+299
-1
lines changed

optimizer/spm_19c_debug/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ To execute the spm.sql script you will need certain privileges. An example is in
44

55
If you don't have a database you can use yourself, take a look at the spooled output in spm.lst
66

7-
In particualr, look at the "Hint Report" section towards the end of the file.
7+
In particular, look at the "Hint Report" section towards the end of the file.
8+
9+
Additional scripts are available in the "in_cache" directory. These scripts us SQL performance analyzer to make it east to check SQL statements in the cursor cache, without the need to run them in SQL plus.
810

911
### DISCLAIMER
1012

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
This directory contains an example of deugging a SQL plan baseline in Oracle Database 19c.
2+
3+
Note: these scripts use SQL performance analyzer.
4+
5+
The scripts make it easy to check SQL statements in the cursor cache.
6+
7+
You can set up an example by running test_setup.sql in a DBA account. Be aware it will drop and create SQL plan baselines. A SQL ID is displayed at the end of the script. You can enter this SQL ID when you run the "spb" scripts.
8+
9+
In most cases, you can use spb_noex.sql - it explains the plan of the relevant SQL statement in the cursor cache.
10+
11+
Alternatively, if you want to test execute the SQL statement, use spb.sql instead.
12+
13+
### DISCLAIMER
14+
15+
* These scripts are provided for educational purposes only.
16+
* They are NOT supported by Oracle World Wide Technical Support.
17+
* The scripts have been tested and they appear to work as intended.
18+
* You should always run scripts on a test instance.
19+
20+
### WARNING
21+
22+
* These scripts drop and create SQL plan baselines. For use on test databases
23+
* You need a license to use SQL performance analyzer to use these scripts
24+
* Check the license user manual for your database version
25+
* Oracle Database 19c: https://docs.oracle.com/en/database/oracle/oracle-database/19/dblic/
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
set echo off
2+
set verify off
3+
set feedback off
4+
set long 10000000
5+
set pagesize 10000
6+
set linesize 250
7+
set trims on
8+
set tab off
9+
column report format a200
10+
11+
whenever sqlerror exit
12+
13+
var ccount number
14+
var spa_task_name varchar2(30);
15+
var execution_name varchar2(30);
16+
var report_text clob;
17+
18+
--
19+
-- You must be licensed to use SPA
20+
--
21+
accept check prompt 'Enter YES/yes if you have a license to use SQL Performance Analyzer: ' default 'NO'
22+
23+
BEGIN
24+
IF upper('&check') != 'YES'
25+
THEN
26+
RAISE_APPLICATION_ERROR(-20001, 'License not confirmed');
27+
END IF;
28+
END;
29+
/
30+
31+
--
32+
-- Get the SQL ID to test
33+
--
34+
accept sqlid prompt 'Enter the SQL ID: '
35+
36+
--
37+
-- Check it's in cache
38+
--
39+
BEGIN
40+
select count(*) into :ccount from v$sql where sql_id = '&sqlid';
41+
IF :ccount = 0
42+
THEN
43+
RAISE_APPLICATION_ERROR(-20002, 'SQL ID not found');
44+
END IF;
45+
END;
46+
/
47+
48+
--
49+
-- Spool the report
50+
--
51+
spool spm_report
52+
53+
exec :spa_task_name := dbms_sqlpa.create_analysis_task(sql_id => '&sqlid');
54+
55+
exec dbms_sqlpa.set_analysis_task_parameter(:spa_task_name, 'disable_multi_exec', 'TRUE');
56+
57+
--
58+
-- Enable the diag mode and run the task
59+
--
60+
alter session set "_sql_plan_management_control"=4;
61+
62+
exec :execution_name := dbms_sqlpa.execute_analysis_task (task_name => :spa_task_name, execution_type => 'execute');
63+
64+
alter session set "_sql_plan_management_control"=0;
65+
66+
--
67+
-- Generate the report
68+
--
69+
exec :report_text := dbms_sqlpa.report_analysis_task (task_name => :spa_task_name, type => 'text', level => 'typical', section => 'all', execution_name => :execution_name);
70+
71+
select :report_text report from dual;
72+
73+
spool off
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
set echo off
2+
set verify off
3+
set feedback off
4+
set long 10000000
5+
set pagesize 10000
6+
set linesize 250
7+
set trims on
8+
set tab off
9+
column report format a200
10+
11+
whenever sqlerror exit
12+
13+
var ccount number
14+
var spa_task_name varchar2(30);
15+
var execution_name varchar2(30);
16+
var report_text clob;
17+
18+
--
19+
-- You must be licensed to use SPA
20+
--
21+
accept check prompt 'Enter YES/yes if you have a license to use SQL Performance Analyzer: ' default 'NO'
22+
23+
24+
BEGIN
25+
IF upper('&check') != 'YES'
26+
THEN
27+
RAISE_APPLICATION_ERROR(-20001, 'License not confirmed');
28+
END IF;
29+
END;
30+
/
31+
32+
--
33+
-- Get the SQL ID to test
34+
--
35+
accept sqlid prompt 'Enter the SQL ID: '
36+
37+
--
38+
-- Check it's in cache
39+
--
40+
BEGIN
41+
select count(*) into :ccount from v$sql where sql_id = '&sqlid';
42+
IF :ccount = 0
43+
THEN
44+
RAISE_APPLICATION_ERROR(-20002, 'SQL ID not found');
45+
END IF;
46+
END;
47+
/
48+
49+
--
50+
-- Spool the report
51+
--
52+
spool spm_report
53+
54+
exec :spa_task_name := dbms_sqlpa.create_analysis_task(sql_id => '&sqlid');
55+
56+
exec dbms_sqlpa.set_analysis_task_parameter(:spa_task_name, 'disable_multi_exec', 'TRUE');
57+
58+
--
59+
-- Enable the diag mode and run the task
60+
--
61+
alter session set "_sql_plan_management_control"=4;
62+
63+
exec :execution_name := dbms_sqlpa.execute_analysis_task (task_name => :spa_task_name, execution_type => 'explain plan');
64+
65+
alter session set "_sql_plan_management_control"=0;
66+
67+
--
68+
-- Generate the report
69+
--
70+
exec :report_text := dbms_sqlpa.report_analysis_task (task_name => :spa_task_name, type => 'text', level => 'typical', section => 'all', execution_name => :execution_name);
71+
72+
select :report_text report from dual;
73+
74+
spool off
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
REPORT
3+
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4+
GENERAL INFORMATION SECTION
5+
-------------------------------------------------------------------------------
6+
Tuning Task Name : TASK_17952
7+
Tuning Task Owner : ADHOC
8+
Workload Type : Single SQL Statement
9+
Execution Count : 1
10+
Current Execution : EXEC_20550
11+
Execution Type : EXPLAIN PLAN
12+
Scope : COMPREHENSIVE
13+
Completion Status : COMPLETED
14+
Started at : 05/25/2021 08:17:28
15+
Completed at : 05/25/2021 08:17:28
16+
17+
-------------------------------------------------------------------------------
18+
Schema Name: ADHOC
19+
SQL ID : 21y39zhmkh4pt
20+
SQL Text : select /* SPM_TEST */ num from example_spm_table where id =
21+
:bindv
22+
Bind Variables :
23+
1 - (NUMBER):100
24+
25+
-------------------------------------------------------------------------------
26+
Explain Plan Statistics
27+
-------------------------------------------------------------------------------
28+
Parse Time (s): .000205
29+
Optimizer Cost: 3
30+
31+
-------------------------------------------------------------------------------
32+
EXPLAIN PLANS SECTION
33+
-------------------------------------------------------------------------------
34+
35+
1- Original
36+
-----------
37+
Plan hash value: 2448381833
38+
39+
---------------------------------------------------------------------------------------
40+
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
41+
---------------------------------------------------------------------------------------
42+
| 0 | SELECT STATEMENT | | 1 | 8 | 3 (0)| 00:00:01 |
43+
|* 1 | TABLE ACCESS FULL| EXAMPLE_SPM_TABLE | 1 | 8 | 3 (0)| 00:00:01 |
44+
---------------------------------------------------------------------------------------
45+
46+
Predicate Information (identified by operation id):
47+
---------------------------------------------------
48+
49+
1 - filter("ID"=:BINDV)
50+
51+
Hint Report (identified by operation id / Query Block Name / Object Alias):
52+
Total hints for statement: 1 (U - Unused (1))
53+
---------------------------------------------------------------------------
54+
55+
1 - SEL$1 / EXAMPLE_SPM_TABLE@SEL$1
56+
U - INDEX_RS_ASC(@"SEL$1" "EXAMPLE_SPM_TABLE"@"SEL$1" ("EXAMPLE_SPM_TABLE"."ID"))
57+
58+
-------------------------------------------------------------------------------
59+
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
--
2+
-- This script sets up a SQL statement with a non-reproducible plan
3+
-- It does this by dropping an index used in the SQL plan baseline plan
4+
-- Be sure to run this script on a TEST SYSTEM ONLY - since it drops SQL plan baselines
5+
--
6+
set echo on
7+
set tab off
8+
set pagesize 1000
9+
set linesize 200
10+
set trims on
11+
12+
var bindv number
13+
var sqlid varchar2(50)
14+
15+
exec select 100 into :bindv from dual;
16+
17+
DECLARE
18+
l_plans_dropped PLS_INTEGER;
19+
BEGIN
20+
FOR REC IN (SELECT DISTINCT SQL_HANDLE FROM DBA_SQL_PLAN_BASELINES where sql_text like '%SPM_TEST%')
21+
LOOP
22+
L_PLANS_DROPPED := DBMS_SPM.DROP_SQL_PLAN_BASELINE (
23+
sql_handle => rec.sql_handle,
24+
PLAN_NAME => NULL);
25+
END LOOP;
26+
END;
27+
/
28+
29+
drop table example_spm_table purge;
30+
31+
create table example_spm_table (id number(10), num number(10), num2 number(10));
32+
create unique index spm_tab_pk on example_spm_table(id);
33+
create index spm_tab_num1 on example_spm_table(num1);
34+
35+
begin
36+
for i in 1..1000
37+
loop
38+
insert into example_spm_table values (i,i,i);
39+
end loop;
40+
end;
41+
/
42+
commit;
43+
44+
exec dbms_stats.gather_table_stats (ownname=>null,tabname=>'example_spm_table');
45+
46+
select /* SPM_TEST */ num from example_spm_table where id = :bindv;
47+
48+
declare
49+
r number;
50+
begin
51+
r:=DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE (attribute_name=>'SQL_TEXT',attribute_value=>'select /* SPM_TEST */ num from example_spm_table where id = :bindv');
52+
end;
53+
/
54+
55+
drop index spm_tab_pk;
56+
57+
select /* SPM_TEST */ num from example_spm_table where id = :bindv;
58+
59+
exec select sql_id into :sqlid from v$sqlarea where sql_text = 'select /* SPM_TEST */ num from example_spm_table where id = :bindv';
60+
61+
select :sqlid from dual;
62+
63+
select sql_text,accepted from dba_sql_plan_baselines where sql_text like '%SPM_TEST%';
64+
65+
select sql_id from v$sql where sql_text = 'select /* SPM_TEST */ num from example_spm_table where id = :bindv';

0 commit comments

Comments
 (0)