More Related Content
Similar to Five more things about Oracle SQL and PLSQL (20)
More from Connor McDonald (20)
Five more things about Oracle SQL and PLSQL
- 2. Five things about
SQL and PLSQL
That you might not have known
Thomas Kyte
http://asktom.oracle.com/
Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
- 3. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
Safe Harbor Statement
The following is intended to outline our general product direction. It is intended for
information purposes only, and may not be incorporated into any contract. It is not a
commitment to deliver any material, code, or functionality, and should not be relied upon
in making purchasing decisions. The development, release, and timing of any features or
functionality described for Oracle’s products remains at the sole discretion of Oracle.
- 4. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
Program Agenda
The optimizer is learning from its mistakes
Functions used, without using a Function
PL/SQL warned you
Location, Location, Location
The most underutilized really cool feature (from five years
ago!)
1
2
3
4
5
- 5. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
Program Agenda
The optimizer is learning from its mistakes
Functions used, without using a Function
PL/SQL warned you
Location, Location, Location
The most underutilized really cool feature (from five years
ago!)
1
2
3
4
5
- 6. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
tkyte%ORA12C> select /*+ gather_plan_statistics */ count(*)
2 from cities_state
3 where name = 'New York city'
4 and state = 'New York'
5 /
COUNT(*)
----------
8175132
- 7. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
-------------------------------------------------------------
| Id | Operation | Name | E-Rows | A-Rows |
-------------------------------------------------------------
| 0 | SELECT STATEMENT | | | 1 |
| 1 | SORT AGGREGATE | | 1 | 1 |
|* 2 | TABLE ACCESS FULL| CITIES_STATE | 3398 | 8175K|
-------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(("NAME"='New York city' AND "STATE"='New York'))
- 8. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
tkyte%ORA12C> select /*+ gather_plan_statistics */ count(*)
2 from cities_state
3 where name = 'New York city'
4 and state = 'New York'
5 /
COUNT(*)
----------
8175132
- 9. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
-------------------------------------------------------------
| Id | Operation | Name | E-Rows | A-Rows |
-------------------------------------------------------------
| 0 | SELECT STATEMENT | | | 1 |
| 1 | SORT AGGREGATE | | 1 | 1 |
|* 2 | TABLE ACCESS FULL| CITIES_STATE | 8175K| 8175K|
-------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(("NAME"='New York city' AND "STATE"='New York'))
Note
-----
- statistics feedback used for this statement
- 10. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
tkyte%ORA12C> exec dbms_spd.flush_sql_plan_directive;
PL/SQL procedure successfully completed.
tkyte%ORA12C> select o.object_name, o.subobject_name col_name,
o.object_type, d.type, d.state, d.reason
2 from dba_sql_plan_directives d, dba_sql_plan_dir_objects o
3 where d.directive_id = o.directive_id
4 and o.owner = user
5 order by 1, 2, 3, 4, 5;
OBJECT_NAME COL_NAME OBJECT TYPE STATE REASON
------------ ---------- ------ ---------------- ---------- ------------------------------------
CITIES_STATE NAME COLUMN DYNAMIC_SAMPLING USABLE SINGLE TABLE CARDINALITY MISESTIMATE
CITIES_STATE STATE COLUMN DYNAMIC_SAMPLING USABLE SINGLE TABLE CARDINALITY MISESTIMATE
CITIES_STATE TABLE DYNAMIC_SAMPLING USABLE SINGLE TABLE CARDINALITY MISESTIMATE
- 11. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
tkyte%ORA12C> select /*+ gather_plan_statistics */ count(*)
2 from cities_state
3 where name = 'Los Angeles city'
4 and state = 'California'
5 /
COUNT(*)
----------
3792620
- 12. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
-------------------------------------------------------------
| Id | Operation | Name | E-Rows | A-Rows |
-------------------------------------------------------------
| 0 | SELECT STATEMENT | | | 1 |
| 1 | SORT AGGREGATE | | 1 | 1 |
|* 2 | TABLE ACCESS FULL| CITIES_STATE | 5196K| 3792K|
-------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(("NAME"='Los Angeles city' AND "STATE"='California'))
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
- 1 Sql Plan Directive used for this statement
- 13. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
tkyte%ORA12C> select column_name, num_distinct, histogram
2 from user_tab_col_statistics
3 where table_name = 'CITIES_STATE';
COLUMN_NAME NUM_DISTINCT HISTOGRAM
----------- ------------ ---------------
NAME 675 NONE
STATE 50 NONE
- 14. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
tkyte%ORA12C> exec dbms_stats.gather_table_stats(user,'CITIES_STATE');
PL/SQL procedure successfully completed.
tkyte%ORA12C> select column_name cname, num_distinct, histogram
2 from user_tab_col_statistics
3 where table_name = 'CITIES_STATE';
CNAME NUM_DISTINCT HISTOGRAM
------------------------------ ------------ ---------------
NAME 675 HYBRID
STATE 50 FREQUENCY
SYS_STS652AVX5KJJE5OOY9V6#UOGP 714 HYBRID
- 15. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
Program Agenda
The optimizer is learning from its mistakes
Functions used, without using a Function
PL/SQL warned you
Location, Location, Location
The most underutilized really cool feature (from five years
ago!)
1
2
3
4
5
- 16. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
Indexes on Expressions, aka FBI’s
• Available since Oracle 8i
• Index an expression
– Create index I on T(f(x));
• An index used to be used ONLY if the expression that was indexed was
referenced
• Since 11.2.0.2, this has changed…
- 17. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> create table t
2 as
3 select *
4 from all_objects;
Table created.
TKYTE@ORA12C> create index t1_idx on t(substr(object_name,1,10));
Index created.
TKYTE@ORA12C> create index t2_idx on t(trunc(created));
Index created.
- 18. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> select *
2 from t
3 where object_name = '12345678901';
no rows selected
--------------------------------------------------------------
| Id | Operation | Name | Rows |
--------------------------------------------------------------
| 0 | SELECT STATEMENT | | |
|* 1 | TABLE ACCESS BY INDEX ROWID BATCHED| T | 2 |
|* 2 | INDEX RANGE SCAN | T1_IDX | 358 |
--------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_NAME"='12345678901')
2 - access("T"."SYS_NC00019$"='1234567890')
- 19. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> select *
2 from t
3 where created = sysdate;
no rows selected
--------------------------------------------------------------
| Id | Operation | Name | Rows |
--------------------------------------------------------------
| 0 | SELECT STATEMENT | | |
|* 1 | TABLE ACCESS BY INDEX ROWID BATCHED| T | 110 |
|* 2 | INDEX RANGE SCAN | T2_IDX | 358 |
--------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("CREATED"=SYSDATE@!)
2 - access("T"."SYS_NC00020$"=TRUNC(SYSDATE@!))
- 20. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
Program Agenda
The optimizer is learning from its mistakes
Functions used, without using a Function
PL/SQL warned you
Location, Location, Location
The most underutilized really cool feature (from five years
ago!)
1
2
3
4
5
- 21. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
Warnings
• PL/SQL Compiler has been warning us since 10.1 (2004!)
• Not widely used
• Can be warnings or compile errors
- 22. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
Warnings
• Severe: code might cause unexpected action or wrong results
• Performance: condition might cause performance issues
• Informational: code as written won’t be wrong or slow – just bad
code
- 23. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> alter session set plsql_warnings='enable:severe';
Session altered.
TKYTE@ORA12C> create or replace procedure p
2 as
3 procedure substr
4 is
5 begin
6 null;
7 end;
8 begin
9 null;
10 end;
11 /
SP2-0804: Procedure created with compilation warnings
TKYTE@ORA12C> show errors
Errors for PROCEDURE P:
LINE/COL ERROR
-------- -----------------------------------------------------------------
1/1 PLW-05018: unit P omitted optional AUTHID clause; default value
DEFINER used
3/19 PLW-05004: identifier SUBSTR is also declared in STANDARD or is a
SQL builtin
- 24. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> alter session set plsql_warnings='enable:performance';
Session altered.
TKYTE@ORA12C> create or replace procedure p
2 as
3 l_string varchar2(5);
4 begin
5 for x in (select * from emp where empno = l_string)
6 loop
7 null;
8 end loop;
9 end;
10 /
SP2-0804: Procedure created with compilation warnings
TKYTE@ORA12C> show errors
Errors for PROCEDURE P:
LINE/COL ERROR
-------- -----------------------------------------------------------------
5/51 PLW-07204: conversion away from column type may result in
sub-optimal query plan
- 25. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> alter session set plsql_warnings='enable:informational';
Session altered.
TKYTE@ORA12C> create or replace procedure p
2 as
3 begin
4 if (null is not null)
5 then
6 dbms_output.put_line( 'hello world' );
7 end if;
8 end;
9 /
SP2-0804: Procedure created with compilation warnings
TKYTE@ORA12C> show errors
Errors for PROCEDURE P:
LINE/COL ERROR
-------- -----------------------------------------------------------------
6/17 PLW-06002: Unreachable code
- 26. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> alter session set
2 plsql_warnings='enable:all,disable:5018,error:6009,error:7204';
Session altered.
TKYTE@ORA12C> create or replace procedure p
2 as
3 begin
4 dbms_output.put_line( 'hello world' );
5 exception
6 when others
7 then null;
8 end;
9 /
Warning: Procedure created with compilation errors.
TKYTE@ORA12C> show errors
Errors for PROCEDURE P:
LINE/COL ERROR
-------- -----------------------------------------------------------------
6/6 PLS-06009: procedure "P" OTHERS handler does not end in RAISE or
RAISE_APPLICATION_ERROR
- 27. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> alter session set Plsql_Warnings = 'enable:all';
Session altered.
TKYTE@ORA12C> create or replace procedure p authid definer
2 as
3 l_date date := to_date( '01-jan-2011', 'dd-mon-yyyy' );
4 l_start number := dbms_utility.get_cpu_time;
5 begin
6 for x in ( select *
7 from big_table
8 where date_string = l_date )
9 loop
10 null;
11 end loop;
12 dbms_output.put_line( 'CPU: ' ||
13 to_char( dbms_utility.get_cpu_time-l_start ) );
14 end;
15 /
SP2-0804: Procedure created with compilation warnings
- 28. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
7 from big_table
8 where date_string = l_date )
9 loop
TKYTE@ORA12C> show errors procedure p
Errors for PROCEDURE P:
LINE/COL ERROR
-------- -----------------------------------------------------------------
8/22 PLW-07204: conversion away from column type may result in
sub-optimal query plan
TKYTE@ORA12C> exec p
CPU: 69003
- 29. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> create or replace procedure p authid definer
2 as
3 l_date varchar2(15) := '01-jan-2011';
4 l_start number := dbms_utility.get_cpu_time;
5 begin
6 for x in ( select *
7 from big_table
8 where date_string = l_date )
9 loop
10 null;
11 end loop;
12 dbms_output.put_line( 'CPU: ' ||
13 to_char( dbms_utility.get_cpu_time-l_start ) );
14 end;
15 /
Procedure created.
TKYTE@ORA12C> exec p
CPU: 343
- 30. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> create table t
2 ( x varchar2(20) constraint t_pk primary key,
3 y varchar2(30)
4 );
Table created.
TKYTE@ORA12C> insert into t
2 select rownum user_id, username
3 from all_users;
39 rows created.
- 31. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> create or replace procedure p authid current_user
2 as
3 l_rec t%rowtype;
4 l_key number := 5;
5 begin
6 select * into l_rec from t where x = l_key;
7 for x in (select plan_table_output
8 from TABLE( dbms_xplan.display_cursor() ) )
9 loop
10 dbms_output.put_line( x.plan_table_output );
11 end loop;
12 end;
13 /
SP2-0804: Procedure created with compilation warnings
- 32. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
5 begin
6 select * into l_rec from t where x = l_key;
7 for x in (select plan_table_output
TKYTE@ORA12C> show errors
Errors for PROCEDURE P:
LINE/COL ERROR
-------- -----------------------------------------------------------------
6/42 PLW-07204: conversion away from column type may result in
sub-optimal query plan
- 33. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> exec p
SQL_ID 18796jgha0hwz, child number 0
-------------------------------------
SELECT * FROM T WHERE X = :B1
Plan hash value: 1601196873
---------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
---------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3 (100)|
|* 1 | TABLE ACCESS FULL| T | 1 | 29 | 3 (0)|
---------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_NUMBER("X")=:B1)
- 34. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> create or replace procedure p authid current_user
2 as
3 l_rec t%rowtype;
4 l_key varchar2(5) := '5';
5 begin
6 select * into l_rec from t where x = l_key;
7 for x in (select plan_table_output
8 from TABLE( dbms_xplan.display_cursor() ) )
9 loop
10 dbms_output.put_line( x.plan_table_output );
11 end loop;
12 end;
13 /
Procedure created.
- 35. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> exec p
SQL_ID 18796jgha0hwz, child number 1
-------------------------------------
SELECT * FROM T WHERE X = :B1
Plan hash value: 1303508680
------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
------------------------------------------------------------
| 0 | SELECT STATEMENT | | | |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 29 |
|* 2 | INDEX UNIQUE SCAN | T_PK | 1 | |
------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("X"=:B1)
- 36. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> CREATE TABLE t
2 (
3 dt date,
4 x int,
5 y varchar2(30)
6 )
7 PARTITION BY RANGE (dt)
8 (
9 PARTITION part1 VALUES
LESS THAN(to_date('31-jan-2011', 'dd-mon-yyyy')),
10 PARTITION part2 VALUES
LESS THAN(to_date('28-feb-2011', 'dd-mon-yyyy'))
11 )
12 /
Table created.
- 37. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> create or replace procedure p authid current_user
2 as
3 l_date timestamp := timestamp'2011-01-15 00:00:00.000';
4 l_count number;
5 begin
6 select count(*) into l_count from t where dt = l_date;
7
8 for x in (select plan_table_output
9 from TABLE( dbms_xplan.display_cursor() ) )
10 loop
11 dbms_output.put_line( '.'||x.plan_table_output );
12 end loop;
13 end;
14 /
SP2-0804: Procedure created with compilation warnings
- 38. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
5 begin
6 select count(*) into l_count from t where dt = l_date;
7
TKYTE@ORA12C> show errors
Errors for PROCEDURE P:
LINE/COL ERROR
-------- -----------------------------------------------------------------
6/47 PLW-07204: conversion away from column type may result in
sub-optimal query plan
- 39. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> exec p
.SQL_ID 0t5m83d3m67q7, child number 1
.-------------------------------------
.SELECT COUNT(*) FROM T WHERE DT = :B1
.
.Plan hash value: 3225603066
.
.---------------------------------------------------------------------
.| Id | Operation | Name | Rows | Bytes | Pstart| Pstop |
.---------------------------------------------------------------------
.| 0 | SELECT STATEMENT | | | | | |
.| 1 | SORT AGGREGATE | | 1 | 9 | | |
.| 2 | PARTITION RANGE ALL| | 1 | 9 | 1 | 2 |
.|* 3 | TABLE ACCESS FULL | T | 1 | 9 | 1 | 2 |
.---------------------------------------------------------------------
.
.Predicate Information (identified by operation id):
.---------------------------------------------------
.
. 3 - filter(INTERNAL_FUNCTION("DT")=:B1)
- 40. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> create or replace procedure p authid current_user
2 as
3 l_date date := to_date( '2011-01-15', 'yyyy-mm-dd' );
4 l_count number;
5 begin
6 select count(*) into l_count from t where dt = l_date;
7
8 for x in (select plan_table_output
9 from TABLE( dbms_xplan.display_cursor() ) )
10 loop
11 dbms_output.put_line( '.'||x.plan_table_output );
12 end loop;
13 end;
14 /
Procedure created.
- 41. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> exec p
.SQL_ID 0t5m83d3m67q7, child number 2
.-------------------------------------
.SELECT COUNT(*) FROM T WHERE DT = :B1
.
.Plan hash value: 3660200434
.
.------------------------------------------------------------------------
.| Id | Operation | Name | Rows | Bytes | Pstart| Pstop |
.------------------------------------------------------------------------
.| 0 | SELECT STATEMENT | | | | | |
.| 1 | SORT AGGREGATE | | 1 | 9 | | |
.| 2 | PARTITION RANGE SINGLE| | 1 | 9 | KEY | KEY |
.|* 3 | TABLE ACCESS FULL | T | 1 | 9 | KEY | KEY |
.------------------------------------------------------------------------
.
.Predicate Information (identified by operation id):
.---------------------------------------------------
. 3 - filter("DT"=:B1)
- 42. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> alter session set Plsql_Warnings = 'error:all';
Session altered.
- 43. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
Warnings
• Can be set at
– The system level ALTER SYSTEM
– The session level ALTER SESSION
– Unit by unit
ALTER PROCEDURE P COMPILE PLSQL_WARNINGS=‘…’ REUSE
SETTINGS;
- 44. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
Program Agenda
The optimizer is learning from its mistakes
Functions used, without using a Function
PL/SQL warned you
Location, Location, Location
The most underutilized really cool feature (from five years
ago!)
1
2
3
4
5
- 45. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
How your data is organized impacts the plan
• Empno, Hiredate and Ename – what is different about the way they arrive?
• An index on Empno or Hiredate would typically be used to retrieve many
more rows from the table then an index on Ename
• There are various techniques we can employ to “cluster” data differently
• Let’s look at the clustering factor first…
- 46. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> create table t1
2 as
3 select chr( ascii('A')+mod(rownum,26) ) ||
to_char(rownum, 'fm00000') key,
4 rpad( 'x', 260, 'x') data
5 from all_objects
6 where rownum <= 26*40;
Table created.
TKYTE@ORA12C> alter table t1 modify (key not null);
Table altered.
TKYTE@ORA12C> create index t1_idx on t1(key);
Index created.
- 47. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> create table t2
2 as
3 select key, data
4 from t1
5 order by key;
Table created.
TKYTE@ORA12C> create index t2_idx on t2(key);
Index created.
- 48. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> select min(cnt), max(cnt), avg(cnt)
2 from (
3 select bno, count(*) cnt
4 from (
5 select dbms_rowid.rowid_block_number( rowid ) bno
6 from t1 /* or t2! */
7 )
8 group by bno
9 )
10 /
MIN(CNT) MAX(CNT) AVG(CNT)
---------- ---------- ----------
26 26 26
- 49. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> select table_name, blocks, num_rows,
to_char(last_analyzed,'dd-mon hh24:mi:ss') la
2 from user_tables
3 where table_name in ('T1','T2')
4 order by 1;
TABLE_NAME BLOCKS NUM_ROWS LA
-------------------- ---------- ---------- ------------------------
T1 45 1040 25-sep 17:34:33
T2 45 1040 25-sep 17:34:33
TKYTE@ORA12C> select table_name, index_name, clustering_factor,
to_char(last_analyzed,'dd-mon hh24:mi:ss') la
2 from user_indexes
3 where table_name in ('T1','T2')
4 order by 1;
TABLE_NAME INDEX_NAME CLUSTERING_FACTOR LA
-------------------- -------------------- ----------------- ----------------
T1 T1_IDX 1040 25-sep 17:34:33
T2 T2_IDX 40 25-sep 17:34:33
- 50. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> select /*+ index( t1 t1_idx ) */ count(data)
2 from t1;
COUNT(DATA)
-----------
1040
TKYTE@ORA12C> select /*+ index( t2 t2_idx ) */ count(data)
2 from t2;
COUNT(DATA)
-----------
1040
- 51. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
select /*+ index( t1 t1_idx ) */ count(data)
from t1
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.00 0 1044 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.00 0.00 0 1044 0 1
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 103
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ----------------------------------------------
1 1 1 SORT AGGREGATE (cr=1044 pr=0 pw=0 time=1920 us
1040 1040 1040 TABLE ACCESS BY INDEX ROWID BATCHED T1 (cr=10
1040 1040 1040 INDEX FULL SCAN T1_IDX (cr=4 pr=0 pw=0 time=
1044-4 = 1040, the clustering factor of T1_IDX
- 52. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
select /*+ index( t2 t2_idx ) */ count(data)
from t2
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.00 0 44 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.00 0.00 0 44 0 1
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 103
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ----------------------------------------------
1 1 1 SORT AGGREGATE (cr=44 pr=0 pw=0 time=1004 us)
1040 1040 1040 TABLE ACCESS BY INDEX ROWID BATCHED T2 (cr=44
1040 1040 1040 INDEX FULL SCAN T2_IDX (cr=4 pr=0 pw=0 time=
44-4 = 40, the clustering factor of T2_IDX
- 53. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> select count(data)
2 from t1
3 where key between 'A00000' and 'A00250';
COUNT(DATA)
-----------
9
TKYTE@ORA12C> select * from table(dbms_xplan.display_cursor);
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 12 (100)|
| 1 | SORT AGGREGATE | | 1 | 268 | |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED| T1 | 9 | 2412 | 12 (0)|
|* 3 | INDEX RANGE SCAN | T1_IDX | 9 | | 2 (0)|
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("KEY">='A00000' AND "KEY"<='A00250')
- 54. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> select count(data)
2 from t2
3 where key between 'A00000' and 'A00250';
COUNT(DATA)
-----------
9
TKYTE@ORA12C> select * from table(dbms_xplan.display_cursor);
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3 (100)|
| 1 | SORT AGGREGATE | | 1 | 268 | |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED| T2 | 9 | 2412 | 3 (0)|
|* 3 | INDEX RANGE SCAN | T2_IDX | 9 | | 2 (0)|
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("KEY">='A00000' AND "KEY"<='A00250')
- 55. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> select count(data)
2 from t1
3 where key between 'A00000' and 'A00500';
COUNT(DATA)
-----------
19
TKYTE@ORA12C> select * from table(dbms_xplan.display_cursor);
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 14 (100)| |
| 1 | SORT AGGREGATE | | 1 | 268 | | |
|* 2 | TABLE ACCESS FULL| T1 | 20 | 5360 | 14 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(("KEY"<='A00500' AND "KEY">='A00000'))
- 56. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> select count(data)
2 from t2
3 where key between 'A00000' and 'A00500';
COUNT(DATA)
-----------
19
TKYTE@ORA12C> select * from table(dbms_xplan.display_cursor);
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3 (100)|
| 1 | SORT AGGREGATE | | 1 | 268 | |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED| T2 | 20 | 5360 | 3 (0)|
|* 3 | INDEX RANGE SCAN | T2_IDX | 20 | | 2 (0)|
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("KEY">='A00000' AND "KEY"<='A00500')
- 57. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> begin
2 dbms_stats.set_table_prefs
3 ( ownname => user,
4 tabname => 'T1',
5 pname => 'TABLE_CACHED_BLOCKS',
6 pvalue => 42 );
7 dbms_stats.set_table_prefs
8 ( ownname => user,
9 tabname => 'T2',
10 pname => 'TABLE_CACHED_BLOCKS',
11 pvalue => 42 );
12
13 dbms_stats.gather_index_stats( user, 'T1_IDX' );
14 dbms_stats.gather_index_stats( user, 'T2_IDX' );
15 end;
16 /
PL/SQL procedure successfully completed.
- 58. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE@ORA12C> select table_name, index_name, clustering_factor,
to_char(last_analyzed,'dd-mon hh24:mi:ss') la
2 from user_indexes
3 where table_name in ('T1','T2')
4 order by 1;
TABLE_NAME INDEX_NAME CLUSTERING_FACTOR LA
-------------------- -------------------- ----------------- ---------------
T1 T1_IDX 40 25-sep 17:34:36
T2 T2_IDX 40 25-sep 17:34:36
- 59. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
Program Agenda
The optimizer is learning from its mistakes
Functions used, without using a Function
PL/SQL warned you
Location, Location, Location
The most underutilized really cool feature (from five years
ago!)
1
2
3
4
5
- 60. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
Quick Story…
I’m going to write a PL/SQL parser…
- 61. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE%ORA12C> create user demo
2 identified by demo;
User created.
TKYTE%ORA12C> grant create session,
2 create procedure
3 to demo;
Grant succeeded.
TKYTE%ORA12C> create edition version2
2 as child of ora$base;
Edition created.
- 62. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE%ORA12C> connect demo/demo
Connected.
DEMO%ORA12C> create or replace
2 procedure my_procedure
3 as
4 begin
5 dbms_output.put_line( 'I am buggy version 1.0' );
6 end;
7 /
Procedure created.
DEMO%ORA12C> create or replace
2 procedure my_procedure2
3 as
4 begin
5 my_procedure;
6 end;
7 /
Procedure created.
- 63. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
DEMO%ORA12C> exec my_procedure2
I am buggy version 1.0
PL/SQL procedure successfully completed.
- 64. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
DEMO%ORA12C> alter session
2 set edition = version2;
ERROR:
ORA-38802: edition does not exist
- 65. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
DEMO%ORA12C> connect tkyte/tkyte
Connected.
TKYTE%ORA12C> alter user demo
2 enable editions;
User altered.
TKYTE%ORA12C> grant use
2 on edition version2
3 to demo;
Grant succeeded.
TKYTE%ORA12C> grant use
2 on edition version2
3 to scott;
Grant succeeded.
- 66. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
TKYTE%ORA12C> connect demo/demo
Connected.
DEMO%ORA12C> alter session
2 set edition = version2;
Session altered.
DEMO%ORA12C> select object_name, object_type, status, edition_name
2 from user_objects;
OBJECT_NAME OBJECT_TYPE STATUS EDITION_NAME
------------------------------ ----------- ------ ------------
MY_PROCEDURE PROCEDURE VALID ORA$BASE
MY_PROCEDURE2 PROCEDURE VALID ORA$BASE
- 67. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
DEMO%ORA12C> create or replace
2 procedure my_procedure
3 as
4 begin
5 dbms_output.put_line( 'I am fixed in version 2.0' );
6 end;
7 /
Procedure created.
- 68. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
DEMO%ORA12C> select object_name, edition_name
2 from user_objects;
OBJECT_NAME EDITION_NAME
------------------------------ ------------
MY_PROCEDURE2 ORA$BASE
MY_PROCEDURE VERSION2
DEMO%ORA12C> select object_name, edition_name
2 from user_objects_AE;
OBJECT_NAME EDITION_NAME
------------------------------ ------------
MY_PROCEDURE ORA$BASE
MY_PROCEDURE2 ORA$BASE
MY_PROCEDURE VERSION2
- 69. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
DEMO%ORA12C> grant execute on my_procedure2 to scott;
Grant succeeded.
DEMO%ORA12C> select object_name, edition_name from user_objects;
OBJECT_NAME EDITION_NAME
------------------------------ ------------
MY_PROCEDURE2 VERSION2
MY_PROCEDURE VERSION2
DEMO%ORA12C> select object_name, edition_name from user_objects_AE;
OBJECT_NAME EDITION_NAME
------------------------------ ------------
MY_PROCEDURE2 ORA$BASE
MY_PROCEDURE ORA$BASE
MY_PROCEDURE2 VERSION2
MY_PROCEDURE VERSION2
- 70. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
DEMO%ORA12C> SELECT SYS_CONTEXT ('userenv', 'current_edition_name') sc
2 FROM DUAL;
SC
---------------
VERSION2
DEMO%ORA12C> exec my_procedure2
I am fixed in version 2.0
PL/SQL procedure successfully completed.
- 71. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
DEMO%ORA12C> connect demo/demo
Connected.
DEMO%ORA12C> SELECT SYS_CONTEXT ('userenv', 'current_edition_name') sc
2 FROM DUAL;
SC
---------------
ORA$BASE
DEMO%ORA12C> exec my_procedure2
I am buggy version 1.0
PL/SQL procedure successfully completed.
- 72. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
DEMO%ORA12C> alter session set edition = version2;
Session altered.
DEMO%ORA12C> SELECT SYS_CONTEXT ('userenv', 'current_edition_name') sc
2 FROM DUAL;
SC
---------------
VERSION2
DEMO%ORA12C> exec my_procedure2
I am fixed in version 2.0
PL/SQL procedure successfully completed.
- 73. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
DEMO%ORA12C> connect scott/tiger
Connected.
SCOTT%ORA12C> SELECT SYS_CONTEXT ('userenv', 'current_edition_name') sc
2 FROM DUAL;
SC
---------------
ORA$BASE
SCOTT%ORA12C> exec demo.my_procedure2
BEGIN demo.my_procedure2; END;
*
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00201: identifier 'DEMO.MY_PROCEDURE2' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
- 74. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
SCOTT%ORA12C> alter session
2 set edition = version2;
Session altered.
SCOTT%ORA12C> exec demo.my_procedure2
I am fixed in version 2.0
PL/SQL procedure successfully completed.
- 75. Copyright © 2014, Oracle and/or its affiliates. All rights reserved. |
Program Agenda
The optimizer is learning from its mistakes
Functions used, without using a Function
PL/SQL warned you
Location, Location, Location
The most underutilized really cool feature (from five years
ago!)
1
2
3
4
5