2026-03-12 20:23:15
This commit is contained in:
35
tpt/ast/01_sql_plan_layout_intro.sql
Normal file
35
tpt/ast/01_sql_plan_layout_intro.sql
Normal file
@@ -0,0 +1,35 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- view merging
|
||||
|
||||
select * from dual;
|
||||
|
||||
select * from table(dbms_xplan.display_cursor);
|
||||
|
||||
create or replace view v as select * from dual;
|
||||
|
||||
select * from (select * from v);
|
||||
|
||||
alter session set "_simple_view_merging"=false;
|
||||
|
||||
select * from (select * from v);
|
||||
|
||||
alter session set "_simple_view_merging"=true;
|
||||
|
||||
select * from (select /*+ NO_MERGE */ * from v);
|
||||
|
||||
select * from (select rownum r, v.* from v);
|
||||
|
||||
|
||||
-- scalar subqueries, run a subquery for populating a value in a single column or a row (9i+)
|
||||
|
||||
select owner, count(*) from test_objects o group by owner;
|
||||
|
||||
-- another way (excludes nulls if any)
|
||||
|
||||
select u.username, (select count(*) from test_objects o where u.username = o.owner) obj_count from test_users u;
|
||||
|
||||
select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
|
||||
|
||||
|
||||
48
tpt/ast/02_advanced_rewrite.sql
Normal file
48
tpt/ast/02_advanced_rewrite.sql
Normal file
@@ -0,0 +1,48 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- GRANT EXECUTE ON sys.dbms_advanced_rewrite TO &user
|
||||
-- there's no public synonym for this package so you should reference it by schema name
|
||||
|
||||
exec sys.DBMS_ADVANCED_REWRITE.DROP_REWRITE_EQUIVALENCE ('test_rewrite');
|
||||
|
||||
begin
|
||||
sys.DBMS_ADVANCED_REWRITE.DECLARE_REWRITE_EQUIVALENCE (
|
||||
'test_rewrite'
|
||||
, 'select username,created from test_users u where username in (select owner from test_objects o where o.owner = u.username)'
|
||||
, 'select /*+ qb_name(main) no_unnest(@subq) */ username,created from test_users u where username in (select /*+ qb_name(subq) */ owner from test_objects o where o.owner = u.username) and /* careful! */ 1=1'
|
||||
, validate => true
|
||||
, rewrite_mode => 'general'
|
||||
);
|
||||
end;
|
||||
/
|
||||
|
||||
|
||||
alter session set query_rewrite_enabled = true -- this is true by default;
|
||||
alter session set query_rewrite_integrity = trusted;
|
||||
|
||||
-- if you see a FILTER operation (not a HASH JOIN SEMI) then the rewrite worked
|
||||
select username,created from test_users u where username in (select owner from test_objects o where o.owner = u.username);
|
||||
@x9a
|
||||
|
||||
|
||||
-- an example of how to add a missing ORDER BY to a statement which assumes that GROUP BY always orders data too
|
||||
-- (this is not true in 10.2+ where GROUP BY and DISTINCT operations can be done using hashing instead of sorting)
|
||||
|
||||
exec sys.DBMS_ADVANCED_REWRITE.DROP_REWRITE_EQUIVALENCE ('test_rewrite_order');
|
||||
|
||||
begin
|
||||
sys.DBMS_ADVANCED_REWRITE.DECLARE_REWRITE_EQUIVALENCE (
|
||||
'test_rewrite_order'
|
||||
, 'select owner,count(*) from test_objects group by owner'
|
||||
, 'select * from (select owner,count(*) from test_objects group by owner order by owner)'
|
||||
, validate => true
|
||||
, rewrite_mode => 'text_match'
|
||||
);
|
||||
end;
|
||||
/
|
||||
|
||||
select owner,count(*) from test_objects group by owner;
|
||||
@x9a
|
||||
|
||||
|
||||
133
tpt/ast/02_badly_correlated.sql
Normal file
133
tpt/ast/02_badly_correlated.sql
Normal file
@@ -0,0 +1,133 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
DROP TABLE badly_correlated1;
|
||||
DROP TABLE badly_correlated2;
|
||||
|
||||
CREATE TABLE badly_correlated1 (id, a, b, c, d, e, f, g, h, val) AS (
|
||||
SELECT rownum id, v.* FROM (
|
||||
SELECT
|
||||
mod(rownum, 100000) a
|
||||
, mod(rownum, 100000) b
|
||||
, mod(rownum, 100000) c
|
||||
, mod(rownum, 100000) d
|
||||
, mod(rownum, 100000) e
|
||||
, mod(rownum, 100000) f
|
||||
, mod(rownum, 100000) g
|
||||
, mod(rownum, 100000) h
|
||||
, lpad('x',100,'x')
|
||||
FROM
|
||||
dual CONNECT BY LEVEL <= 100000
|
||||
UNION ALL
|
||||
SELECT
|
||||
90 a
|
||||
, 91 b
|
||||
, 92 c
|
||||
, 93 d
|
||||
, 94 e
|
||||
, 95 f
|
||||
, 96 g
|
||||
, 97 h
|
||||
, lpad('y',100,'y')
|
||||
FROM
|
||||
dual CONNECT BY LEVEL <= 100000
|
||||
) v
|
||||
)
|
||||
/
|
||||
|
||||
CREATE TABLE badly_correlated2 AS SELECT * FROM badly_correlated1;
|
||||
|
||||
ALTER TABLE badly_correlated1 MODIFY id PRIMARY KEY;
|
||||
ALTER TABLE badly_correlated2 MODIFY id PRIMARY KEY;
|
||||
|
||||
CREATE INDEX idx1_badly_correlated1 ON badly_correlated1 (a,b,c,d,e,f,g);
|
||||
CREATE INDEX idx1_badly_correlated2 ON badly_correlated2 (a,b,c,d,e,f,g);
|
||||
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'BADLY_CORRELATED1', method_opt=>'FOR TABLE', cascade=>true);
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'BADLY_CORRELATED2', method_opt=>'FOR TABLE', cascade=>true);
|
||||
|
||||
|
||||
select /*+ opt_param('_optimizer_use_feedback', 'false') */
|
||||
*
|
||||
from
|
||||
badly_correlated1 t1
|
||||
, badly_correlated2 t2
|
||||
where
|
||||
t1.id = t2.id
|
||||
and t1.a = 90
|
||||
and t1.b = 91
|
||||
and t1.c = 92
|
||||
and t1.d = 93
|
||||
and t1.e = 94
|
||||
and t1.f = 95
|
||||
and t1.g = 96
|
||||
and t1.h = 97
|
||||
and t2.val like 'xy%'
|
||||
/
|
||||
|
||||
@x
|
||||
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'BADLY_CORRELATED1', method_opt=>'FOR TABLE FOR ALL COLUMNS SIZE 254', cascade=>true);
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'BADLY_CORRELATED2', method_opt=>'FOR TABLE FOR ALL COLUMNS SIZE 254', cascade=>true);
|
||||
|
||||
select /*+ opt_param('_optimizer_use_feedback', 'false') */
|
||||
*
|
||||
from
|
||||
badly_correlated1 t1
|
||||
, badly_correlated2 t2
|
||||
where
|
||||
t1.id = t2.id
|
||||
and t1.a = 90
|
||||
and t1.b = 91
|
||||
and t1.c = 92
|
||||
and t1.d = 93
|
||||
and t1.e = 94
|
||||
and t1.f = 95
|
||||
and t1.g = 96
|
||||
and t1.h = 97
|
||||
and t2.val like 'xy%'
|
||||
/
|
||||
|
||||
@x
|
||||
|
||||
-- create extended stats
|
||||
select
|
||||
dbms_stats.create_extended_stats(
|
||||
ownname => user
|
||||
, tabname=>'BADLY_CORRELATED1'
|
||||
, extension=>'(a,b,c,d,e,f,g,h)'
|
||||
)
|
||||
from dual
|
||||
/
|
||||
|
||||
select
|
||||
dbms_stats.create_extended_stats(
|
||||
ownname => user
|
||||
, tabname=>'BADLY_CORRELATED2'
|
||||
, extension=>'(a,b,c,d,e,f,g,h)'
|
||||
)
|
||||
from dual
|
||||
/
|
||||
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'BADLY_CORRELATED1', method_opt=>'FOR TABLE FOR ALL COLUMNS SIZE 254', cascade=>true);
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'BADLY_CORRELATED2', method_opt=>'FOR TABLE FOR ALL COLUMNS SIZE 254', cascade=>true);
|
||||
|
||||
select /*+ opt_param('_optimizer_use_feedback', 'false') */
|
||||
*
|
||||
from
|
||||
badly_correlated1 t1
|
||||
, badly_correlated2 t2
|
||||
where
|
||||
t1.id = t2.id
|
||||
and t1.a = 90
|
||||
and t1.b = 91
|
||||
and t1.c = 92
|
||||
and t1.d = 93
|
||||
and t1.e = 94
|
||||
and t1.f = 95
|
||||
and t1.g = 96
|
||||
and t1.h = 97
|
||||
and t2.val like 'xy%'
|
||||
/
|
||||
|
||||
@x
|
||||
126
tpt/ast/02_bind_peeking_nested_loops.sql
Normal file
126
tpt/ast/02_bind_peeking_nested_loops.sql
Normal file
@@ -0,0 +1,126 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- File name: demos/bind_peeking_nested_loops.sql
|
||||
-- Purpose: this script demos how a "wrong" bind variable value
|
||||
-- can cause an execution plan to be compiled which is
|
||||
-- very inefficient for the next execution with different bind variable
|
||||
-- values (with large number of matching rows)
|
||||
-- the second execution of the query takes very long time to complete
|
||||
-- despite adaptive bind variable peeking, which would kick in during the
|
||||
-- next (3rd) execution
|
||||
--
|
||||
-- This problem happens even on Oracle 11.2 despite adaptive bind peeking
|
||||
-- and cardinality feedback (due to design, not a bug)
|
||||
--
|
||||
-- Author: Tanel Poder (tanel@e2sn.com)
|
||||
-- Copyright: (c) http://tech.e2sn.com
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
alter session set optimizer_use_sql_plan_baselines = false;
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t3;
|
||||
DROP TABLE t4;
|
||||
DROP TABLE t5;
|
||||
|
||||
CREATE TABLE t1 AS SELECT * FROM dba_objects WHERE rownum <= 50000;
|
||||
CREATE TABLE t2 AS SELECT * FROM dba_objects WHERE rownum <= 10000;
|
||||
CREATE TABLE t3 AS SELECT * FROM dba_objects WHERE rownum <= 10000;
|
||||
CREATE TABLE t4 AS SELECT * FROM dba_objects WHERE rownum <= 10000;
|
||||
CREATE TABLE t5 AS SELECT * FROM dba_objects WHERE rownum <= 10000;
|
||||
|
||||
CREATE INDEX i1 ON t1(owner);
|
||||
CREATE INDEX i2 ON t2(owner);
|
||||
CREATE INDEX i3 ON t3(owner);
|
||||
CREATE INDEX i4 ON t4(owner);
|
||||
CREATE INDEX i5 ON t5(owner);
|
||||
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T1',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 254');
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T2',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 254');
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T3',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 254');
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T4',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 254');
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T5',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 254');
|
||||
-- EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T1',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');
|
||||
-- EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T2',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');
|
||||
-- EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T3',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');
|
||||
-- EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T4',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');
|
||||
-- EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T5',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');
|
||||
|
||||
-- this hack might be needed to "help" this problem to show up sometimes:
|
||||
-- ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ=10;
|
||||
|
||||
VAR v1 VARCHAR2(100)
|
||||
VAR v2 VARCHAR2(100)
|
||||
VAR v3 VARCHAR2(100)
|
||||
VAR v4 VARCHAR2(100)
|
||||
VAR v5 VARCHAR2(100)
|
||||
|
||||
EXEC :v1:='SCOTT'
|
||||
EXEC :v2:='SCOTT'
|
||||
EXEC :v3:='SCOTT'
|
||||
EXEC :v4:='SCOTT'
|
||||
EXEC :v5:='SCOTT'
|
||||
|
||||
SET TIMING ON
|
||||
|
||||
PROMPT Running query first time, this should be fast (and should use nested loops execution plan)
|
||||
|
||||
SELECT
|
||||
MIN(t1.created), MAX(t1.created)
|
||||
FROM
|
||||
t1
|
||||
, t2
|
||||
, t3
|
||||
, t4
|
||||
, t5
|
||||
WHERE
|
||||
t1.object_id = t2.object_id
|
||||
AND t2.object_id = t3.object_id
|
||||
AND t3.object_id = t4.object_id
|
||||
AND t4.object_id = t5.object_id
|
||||
AND t1.owner = :v1
|
||||
AND t2.owner = :v2
|
||||
AND t3.owner = :v3
|
||||
AND t4.owner = :v4
|
||||
AND t5.owner = :v5
|
||||
/
|
||||
|
||||
SET TIMING OFF
|
||||
|
||||
--SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null,null,'ALLSTATS LAST ADVANCED'));
|
||||
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null,null));
|
||||
|
||||
EXEC :v1:='SYS'
|
||||
EXEC :v2:='SYS'
|
||||
EXEC :v3:='SYS'
|
||||
EXEC :v4:='SYS'
|
||||
EXEC :v5:='SYS'
|
||||
|
||||
SET TIMING ON
|
||||
|
||||
PROMPT Now running the same query with different bind variables (this query should take very long time)
|
||||
|
||||
SELECT
|
||||
MIN(t1.created), MAX(t1.created)
|
||||
FROM
|
||||
t1
|
||||
, t2
|
||||
, t3
|
||||
, t4
|
||||
, t5
|
||||
WHERE
|
||||
t1.object_id = t2.object_id
|
||||
AND t2.object_id = t3.object_id
|
||||
AND t3.object_id = t4.object_id
|
||||
AND t4.object_id = t5.object_id
|
||||
AND t1.owner = :v1
|
||||
AND t2.owner = :v2
|
||||
AND t3.owner = :v3
|
||||
AND t4.owner = :v4
|
||||
AND t5.owner = :v5
|
||||
/
|
||||
|
||||
87
tpt/ast/02_bind_peeking_nested_loops_2.sql
Normal file
87
tpt/ast/02_bind_peeking_nested_loops_2.sql
Normal file
@@ -0,0 +1,87 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- File name: demos/bind_peeking_nested_loops.sql
|
||||
-- Purpose: this script demos how a "wrong" bind variable value
|
||||
-- can cause an execution plan to be compiled which is
|
||||
-- very inefficient for the next execution with different bind variable
|
||||
-- values (with large number of matching rows)
|
||||
-- the second execution of the query takes very long time to complete
|
||||
-- despite adaptive bind variable peeking, which would kick in during the
|
||||
-- next (3rd) execution
|
||||
--
|
||||
-- This problem happens even on Oracle 11.2 despite adaptive bind peeking
|
||||
-- and cardinality feedback (due design, not a bug)
|
||||
--
|
||||
-- Author: Tanel Poder (tanel@e2sn.com)
|
||||
-- Copyright: (c) http://tech.e2sn.com
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t3;
|
||||
|
||||
CREATE TABLE t1 AS SELECT * FROM dba_objects;
|
||||
CREATE TABLE t2 AS SELECT * FROM dba_objects;
|
||||
CREATE TABLE t3 AS SELECT * FROM dba_objects;
|
||||
|
||||
CREATE INDEX i1 ON t1(owner);
|
||||
CREATE INDEX i2 ON t2(owner);
|
||||
CREATE INDEX i3 ON t3(owner);
|
||||
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T1',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 254');
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T2',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 254');
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T3',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 254');
|
||||
|
||||
ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ=10;
|
||||
|
||||
VAR v VARCHAR2(100)
|
||||
|
||||
EXEC :v:='SYS'
|
||||
|
||||
SET TIMING ON
|
||||
|
||||
PROMPT Running query first time, this should be fast (and should use nested loops execution plan)
|
||||
|
||||
SELECT
|
||||
MIN(t1.created), MAX(t1.created)
|
||||
FROM
|
||||
t1
|
||||
, t2
|
||||
, t3
|
||||
WHERE
|
||||
t1.object_id = t2.object_id
|
||||
AND t2.object_id = t3.object_id
|
||||
AND t1.owner = :v
|
||||
AND t2.owner = :v
|
||||
AND t3.owner = :v
|
||||
/
|
||||
|
||||
SET TIMING OFF
|
||||
|
||||
--SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null,null,'ALLSTATS LAST ADVANCED'));
|
||||
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null,null));
|
||||
|
||||
EXEC :v:='SCOTT'
|
||||
|
||||
SET TIMING ON
|
||||
|
||||
PROMPT Now running the same query with different bind variables (this query should take very long time)
|
||||
|
||||
SELECT
|
||||
MIN(t1.created), MAX(t1.created)
|
||||
FROM
|
||||
t1
|
||||
, t2
|
||||
, t3
|
||||
WHERE
|
||||
t1.object_id = t2.object_id
|
||||
AND t2.object_id = t3.object_id
|
||||
AND t1.owner = :v
|
||||
AND t2.owner = :v
|
||||
AND t3.owner = :v
|
||||
/
|
||||
|
||||
87
tpt/ast/02_bind_peeking_nested_loops_nohist.sql
Normal file
87
tpt/ast/02_bind_peeking_nested_loops_nohist.sql
Normal file
@@ -0,0 +1,87 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- File name: demos/bind_peeking_nested_loops.sql
|
||||
-- Purpose: this script demos how a "wrong" bind variable value
|
||||
-- can cause an execution plan to be compiled which is
|
||||
-- very inefficient for the next execution with different bind variable
|
||||
-- values (with large number of matching rows)
|
||||
-- the second execution of the query takes very long time to complete
|
||||
-- despite adaptive bind variable peeking, which would kick in during the
|
||||
-- next (3rd) execution
|
||||
--
|
||||
-- This problem happens even on Oracle 11.2 despite adaptive bind peeking
|
||||
-- and cardinality feedback (due design, not a bug)
|
||||
--
|
||||
-- Author: Tanel Poder (tanel@e2sn.com)
|
||||
-- Copyright: (c) http://tech.e2sn.com
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t3;
|
||||
|
||||
CREATE TABLE t1 AS SELECT * FROM dba_objects;
|
||||
CREATE TABLE t2 AS SELECT * FROM dba_objects;
|
||||
CREATE TABLE t3 AS SELECT * FROM dba_objects;
|
||||
|
||||
CREATE INDEX i1 ON t1(owner);
|
||||
CREATE INDEX i2 ON t2(owner);
|
||||
CREATE INDEX i3 ON t3(owner);
|
||||
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T1',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T2',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T3',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');
|
||||
|
||||
ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ=10;
|
||||
|
||||
VAR v VARCHAR2(100)
|
||||
|
||||
EXEC :v:='SCOTT'
|
||||
|
||||
SET TIMING ON
|
||||
|
||||
PROMPT Running query first time, this should be fast (and should use nested loops execution plan)
|
||||
|
||||
SELECT
|
||||
MIN(t1.created), MAX(t1.created)
|
||||
FROM
|
||||
t1
|
||||
, t2
|
||||
, t3
|
||||
WHERE
|
||||
t1.object_id = t2.object_id
|
||||
AND t2.object_id = t3.object_id
|
||||
AND t1.owner = :v
|
||||
AND t2.owner = :v
|
||||
AND t3.owner = :v
|
||||
/
|
||||
|
||||
SET TIMING OFF
|
||||
|
||||
--SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null,null,'ALLSTATS LAST ADVANCED'));
|
||||
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null,null));
|
||||
|
||||
EXEC :v:='SYS'
|
||||
|
||||
SET TIMING ON
|
||||
|
||||
PROMPT Now running the same query with different bind variables (this query should take very long time)
|
||||
|
||||
SELECT
|
||||
MIN(t1.created), MAX(t1.created)
|
||||
FROM
|
||||
t1
|
||||
, t2
|
||||
, t3
|
||||
WHERE
|
||||
t1.object_id = t2.object_id
|
||||
AND t2.object_id = t3.object_id
|
||||
AND t1.owner = :v
|
||||
AND t2.owner = :v
|
||||
AND t3.owner = :v
|
||||
/
|
||||
|
||||
98
tpt/ast/02_bind_peeking_nested_loops_proc.sql
Normal file
98
tpt/ast/02_bind_peeking_nested_loops_proc.sql
Normal file
@@ -0,0 +1,98 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- File name: demos/bind_peeking_nested_loops.sql
|
||||
-- Purpose: this script demos how a "wrong" bind variable value
|
||||
-- can cause an execution plan to be compiled which is
|
||||
-- very inefficient for the next execution with different bind variable
|
||||
-- values (with large number of matching rows)
|
||||
-- the second execution of the query takes very long time to complete
|
||||
-- despite adaptive bind variable peeking, which would kick in during the
|
||||
-- next (3rd) execution
|
||||
--
|
||||
-- This problem happens even on Oracle 11.2 despite adaptive bind peeking
|
||||
-- and cardinality feedback (due to design, not a bug)
|
||||
--
|
||||
-- Author: Tanel Poder (tanel@e2sn.com)
|
||||
-- Copyright: (c) http://tech.e2sn.com
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
alter session set optimizer_use_sql_plan_baselines = false;
|
||||
|
||||
DROP TABLE t_bp1;
|
||||
DROP TABLE t_bp2;
|
||||
DROP TABLE t_bp3;
|
||||
DROP TABLE t_bp4;
|
||||
DROP TABLE t_bp5;
|
||||
|
||||
CREATE TABLE t_bp1 AS SELECT * FROM dba_objects WHERE rownum <= 50000;
|
||||
CREATE TABLE t_bp2 AS SELECT * FROM dba_objects WHERE rownum <= 10000;
|
||||
CREATE TABLE t_bp3 AS SELECT * FROM dba_objects WHERE rownum <= 10000;
|
||||
CREATE TABLE t_bp4 AS SELECT * FROM dba_objects WHERE rownum <= 10000;
|
||||
CREATE TABLE t_bp5 AS SELECT * FROM dba_objects WHERE rownum <= 10000;
|
||||
|
||||
CREATE INDEX i_bp1 ON t_bp1(owner);
|
||||
CREATE INDEX i_bp2 ON t_bp2(owner);
|
||||
CREATE INDEX i_bp3 ON t_bp3(owner);
|
||||
CREATE INDEX i_bp4 ON t_bp4(owner);
|
||||
CREATE INDEX i_bp5 ON t_bp5(owner);
|
||||
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T_BP1',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 254');
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T_BP2',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 254');
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T_BP3',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 254');
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T_BP4',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 254');
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T_BP5',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 254');
|
||||
-- EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T1',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');
|
||||
-- EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T2',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');
|
||||
-- EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T3',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');
|
||||
-- EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T4',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');
|
||||
-- EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T5',cascade=>TRUE, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');
|
||||
|
||||
-- this hack might be needed to "help" this problem to show up sometimes:
|
||||
-- ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ=10;
|
||||
|
||||
CREATE OR REPLACE PROCEDURE test_bp (num_loops IN NUMBER, sleep IN NUMBER
|
||||
, v1 IN VARCHAR2, v2 IN VARCHAR2, v3 IN VARCHAR2, v4 IN VARCHAR2, v5 IN VARCHAR2)
|
||||
AS
|
||||
r1 DATE;
|
||||
r2 DATE;
|
||||
s NUMBER;
|
||||
BEGIN
|
||||
FOR i IN 1..num_loops LOOP
|
||||
SELECT /*+ opt_param('_optimizer_use_feedback', 'false') */
|
||||
MIN(t_bp1.created), MAX(t_bp5.created) INTO r1, r2
|
||||
FROM
|
||||
t_bp1
|
||||
, t_bp2
|
||||
, t_bp3
|
||||
, t_bp4
|
||||
, t_bp5
|
||||
WHERE
|
||||
t_bp1.object_id = t_bp2.object_id
|
||||
AND t_bp2.object_id = t_bp3.object_id
|
||||
AND t_bp3.object_id = t_bp4.object_id
|
||||
AND t_bp4.object_id = t_bp5.object_id
|
||||
AND t_bp1.owner = v1
|
||||
AND t_bp2.owner = v2
|
||||
AND t_bp3.owner = v3
|
||||
AND t_bp4.owner = v4
|
||||
AND t_bp5.owner = v5;
|
||||
|
||||
s := s + (r2 - r1); -- dummy calculation
|
||||
IF sleep > 0 THEN DBMS_LOCK.SLEEP(sleep); END IF;
|
||||
END LOOP;
|
||||
DBMS_OUTPUT.PUT_LINE(TO_CHAR(s));
|
||||
END;
|
||||
/
|
||||
|
||||
PROMPT Running query first time, this should be fast (and should use nested loops execution plan)
|
||||
|
||||
|
||||
--SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null,null));
|
||||
|
||||
SET TIMING ON
|
||||
|
||||
PROMPT Now running the same query with different bind variables (this query should take very long time)
|
||||
|
||||
111
tpt/ast/02_choosing_join_order.sql
Normal file
111
tpt/ast/02_choosing_join_order.sql
Normal file
@@ -0,0 +1,111 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- File name: 02_choosing_join_order.sql
|
||||
--
|
||||
-- Purpose: Advanced Oracle SQL Tuning demo script
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Usage: You can run the query against Oracle's sample schemas (SH)
|
||||
-- The optimizer stats have to be updated to cause trouble.
|
||||
-- See the commented out code below
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- in Oracle 11gR2, set the cardinality feedback option to false for demo stability purposes
|
||||
-- alter session set "_optimizer_use_feedback"=false;
|
||||
--
|
||||
-- Set statistics_level = all for measuring optimizer misestimate (or use V$SQL_MONITOR):
|
||||
-- alter session set statistics_level = all;
|
||||
--
|
||||
-- Cause trouble for the optimizer:
|
||||
-- EXEC DBMS_STATS.SET_TABLE_STATS('SH','CUSTOMERS', NUMROWS=>1, NUMBLKS=>1, NO_INVALIDATE=>FALSE);
|
||||
|
||||
SELECT /*+ MONITOR */
|
||||
ch.channel_desc
|
||||
, co.country_iso_code co
|
||||
, cu.cust_city
|
||||
, p.prod_category
|
||||
, sum(s.quantity_sold)
|
||||
, sum(s.amount_sold)
|
||||
FROM
|
||||
sh.sales s
|
||||
, sh.customers cu
|
||||
, sh.countries co
|
||||
, sh.products p
|
||||
, sh.channels ch
|
||||
WHERE
|
||||
-- join
|
||||
s.cust_id = cu.cust_id
|
||||
AND cu.country_id = co.country_id
|
||||
AND s.prod_id = p.prod_id
|
||||
AND s.channel_id = ch.channel_id
|
||||
-- filter
|
||||
AND ch.channel_class = 'Direct'
|
||||
AND co.country_iso_code = 'US'
|
||||
AND p.prod_category = 'Electronics'
|
||||
GROUP BY
|
||||
ch.channel_desc
|
||||
, co.country_iso_code
|
||||
, cu.cust_city
|
||||
, p.prod_category
|
||||
/
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
-- SQL Profiles (require Tuning + Diag Pack):
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- VAR sql_fulltext CLOB
|
||||
-- EXEC SELECT sql_fulltext INTO :sql_fulltext FROM v$sql WHERE sql_id = '1ka5g0kh4h6pc' AND rownum = 1;
|
||||
--
|
||||
-- Example 1: Set Join order:
|
||||
-- EXEC DBMS_SQLTUNE.IMPORT_SQL_PROFILE(sql_text=>:sql_fulltext, profile=>sys.sqlprof_attr('LEADING(@"SEL$1" "CO"@"SEL$1" "CH"@"SEL$1" "CU"@"SEL$1" "S"@"SEL$1" "P"@"SEL$1")'), name=> 'MANUAL_PROFILE_1ka5g0kh4h6pc');
|
||||
--
|
||||
-- Example 2: Adjust cardinality:
|
||||
-- EXEC DBMS_SQLTUNE.IMPORT_SQL_PROFILE(sql_text=>:sql_fulltext, profile=>sys.sqlprof_attr('CARDINALITY(@"SEL$1" "CU"@"SEL$1" 100000)'), name=> 'MANUAL_PROFILE_1ka5g0kh4h6pc');
|
||||
--
|
||||
-- Example 3: Set multiple hints:
|
||||
-- DECLARE
|
||||
-- hints sys.sqlprof_attr := sys.sqlprof_attr(
|
||||
-- ('LEADING(@"SEL$1" "CO"@"SEL$1" "CH"@"SEL$1"')
|
||||
-- , ('CARDINALITY(@"SEL$1" "CU"@"SEL$1" 100000)')
|
||||
-- );
|
||||
-- BEGIN
|
||||
-- DBMS_SQLTUNE.IMPORT_SQL_PROFILE(sql_text=>:sql_fulltext, profile=> hints, name=> 'MANUAL_PROFILE_1ka5g0kh4h6pc');
|
||||
-- END;
|
||||
-- /
|
||||
--
|
||||
-- Drop the profile:
|
||||
-- EXEC DBMS_SQLTUNE.DROP_SQL_PROFILE('MANUAL_PROFILE_1ka5g0kh4h6pc');
|
||||
--
|
||||
--
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
-- SQL Plan Baselines - DBMS_SPM in EE licenses - see http://jonathanlewis.wordpress.com/2011/01/12/fake-baselines/
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
-- bad_sqlid = 1ka5g0kh4h6pc
|
||||
-- good_sqlid = 1fzf3vqv0f49q
|
||||
|
||||
-- 1) Manually run the query with hints, params, etc to get the plan you want (the good query)
|
||||
--
|
||||
-- 2) Create a disabled plan baseline for the "bad query":
|
||||
-- VAR x NUMBER
|
||||
-- EXEC :x:= DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE('&bad_sqlid', enabled=>'NO');
|
||||
--
|
||||
-- 3) SELECT sql_handle FROM dba_sql_plan_baselines WHERE sql_text = '<your sql_text>';
|
||||
--
|
||||
-- 4) Associate the "good query" plan with the "bad query" SQL plan baseline:
|
||||
-- DEF good_sql_id = 1fzf3vqv0f49q
|
||||
-- DEF good_plan_hash_value = 2863714589
|
||||
-- DEF sql_handle_for_original = SQL_4b3ef772af37954d
|
||||
|
||||
-- VAR x NUMBER
|
||||
--
|
||||
-- exec :x := dbms_spm.load_plans_from_cursor_cache( -
|
||||
-- sql_id => '&good_sql_id', -
|
||||
-- plan_hash_value => &good_plan_hash_value, -
|
||||
-- sql_handle => '&sql_handle_for_original');
|
||||
--
|
||||
25
tpt/ast/02_distinct_agg_transform.sql
Normal file
25
tpt/ast/02_distinct_agg_transform.sql
Normal file
@@ -0,0 +1,25 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- TODO: not working yet
|
||||
-- LEADING hint sets the order properly but not the ORDERED hint
|
||||
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
|
||||
create table t1 as select * from all_objects;
|
||||
create table t2 as select * from all_objects;
|
||||
|
||||
create index i1 on t2(object_id);
|
||||
|
||||
exec dbms_stats.gather_table_stats(user,'T1');
|
||||
exec dbms_stats.gather_table_stats(user,'T2');
|
||||
|
||||
-- ordered hint "ignored" starting from 11.2.0.1 thanks to distinct aggregation transformation
|
||||
|
||||
select /*+ ORDERED */ t1.owner, count(distinct t2.object_type) from t2, t1 where t1.object_id = t2.object_id group by t1.owner;
|
||||
@x
|
||||
|
||||
select /*+ ORDERED NO_TRANSFORM_DISTINCT_AGG */ t1.owner, count(distinct t2.object_type) from t2, t1 where t1.object_id = t2.object_id group by t1.owner;
|
||||
@x
|
||||
|
||||
73
tpt/ast/02_join_nested_loops.sql
Normal file
73
tpt/ast/02_join_nested_loops.sql
Normal file
@@ -0,0 +1,73 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
set echo on
|
||||
|
||||
select
|
||||
t.owner, t.created, i.last_ddl_time
|
||||
from
|
||||
test_objects t
|
||||
, indexed_objects i
|
||||
where
|
||||
t.object_id = i.object_id
|
||||
and t.owner = 'SH'
|
||||
and t.object_name like 'S%'
|
||||
/
|
||||
|
||||
@xall
|
||||
|
||||
|
||||
select /*+ LEADING(t,i) USE_NL(i) */
|
||||
t.owner, t.created, i.last_ddl_time
|
||||
from
|
||||
test_objects t
|
||||
, indexed_objects i
|
||||
where
|
||||
t.object_id = i.object_id
|
||||
and t.owner = 'SH'
|
||||
and t.object_name like 'S%'
|
||||
/
|
||||
|
||||
@xall
|
||||
|
||||
|
||||
select /*+ LEADING(t,i) USE_NL(i) NO_NLJ_PREFETCH(i) */
|
||||
t.owner, t.created, i.last_ddl_time
|
||||
from
|
||||
test_objects t
|
||||
, indexed_objects i
|
||||
where
|
||||
t.object_id = i.object_id
|
||||
and t.owner = 'SH'
|
||||
and t.object_name like 'S%'
|
||||
/
|
||||
|
||||
@xall
|
||||
|
||||
select /*+ LEADING(t,i) USE_NL(i) NO_NLJ_BATCHING(i) */
|
||||
t.owner, t.created, i.last_ddl_time
|
||||
from
|
||||
test_objects t
|
||||
, indexed_objects i
|
||||
where
|
||||
t.object_id = i.object_id
|
||||
and t.owner = 'SH'
|
||||
and t.object_name like 'S%'
|
||||
/
|
||||
|
||||
@xall
|
||||
|
||||
select /*+ LEADING(t,i) USE_NL(i) NO_NLJ_PREFETCH(t) NO_NLJ_PREFETCH(i) NO_NLJ_BATCHING(t) NO_NLJ_BATCHING(i) */
|
||||
t.owner, t.created, i.last_ddl_time
|
||||
from
|
||||
test_objects t
|
||||
, indexed_objects i
|
||||
where
|
||||
t.object_id = i.object_id
|
||||
and t.owner = 'SH'
|
||||
and t.object_name like 'S%'
|
||||
/
|
||||
|
||||
@xall
|
||||
|
||||
set echo off
|
||||
25
tpt/ast/02_leading_sq.sql
Normal file
25
tpt/ast/02_leading_sq.sql
Normal file
@@ -0,0 +1,25 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
select
|
||||
/*+
|
||||
no_unnest(@my_sub)
|
||||
leading (@my_sub emp_inner@my_sub)
|
||||
use_merge (@my_sub dept_inner@my_sub)
|
||||
*/
|
||||
*
|
||||
from
|
||||
scott.emp emp_outer
|
||||
where
|
||||
emp_outer.deptno in (
|
||||
select /*+ qb_name(my_sub) */
|
||||
dept_inner.deptno
|
||||
from
|
||||
scott.dept dept_inner
|
||||
, scott.emp emp_inner
|
||||
where
|
||||
dept_inner.dname like 'S%'
|
||||
and emp_inner.ename = dept_inner.dname
|
||||
and dept_inner.deptno = emp_outer.deptno
|
||||
)
|
||||
/
|
||||
176
tpt/ast/02_outline_force_plan_from_cursor.sql
Normal file
176
tpt/ast/02_outline_force_plan_from_cursor.sql
Normal file
@@ -0,0 +1,176 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- Advanced Oracle SQL Tuning
|
||||
|
||||
-- when testing purposes on 11g+
|
||||
ALTER SESSION SET "_optimizer_use_feedback"=FALSE;
|
||||
|
||||
--exec dbms_outln.drop_unused;
|
||||
exec dbms_outln.drop_by_cat('TEMP_SWAP_OUTLINE');
|
||||
exec dbms_outln.drop_by_cat('TEMP_SWAP_OUTLINE_BAD');
|
||||
exec dbms_outln.drop_by_cat('TEMP_SWAP_OUTLINE_GOOD');
|
||||
-- this command will drop all default outlines!!!
|
||||
exec dbms_outln.drop_by_cat('DEFAULT');
|
||||
|
||||
delete from ol$;
|
||||
delete from ol$hints;
|
||||
delete from ol$nodes;
|
||||
COMMIT;
|
||||
|
||||
ALTER SYSTEM FLUSH SHARED_POOL;
|
||||
|
||||
-- bad original query
|
||||
SELECT
|
||||
ch.channel_desc
|
||||
, co.country_iso_code co
|
||||
, cu.cust_city
|
||||
, p.prod_category
|
||||
, sum(s.quantity_sold)
|
||||
, sum(s.amount_sold)
|
||||
FROM
|
||||
sh.sales s
|
||||
, sh.customers cu
|
||||
, sh.countries co
|
||||
, sh.products p
|
||||
, sh.channels ch
|
||||
WHERE
|
||||
-- join
|
||||
s.cust_id = cu.cust_id
|
||||
AND cu.country_id = co.country_id
|
||||
AND s.prod_id = p.prod_id
|
||||
AND s.channel_id = ch.channel_id
|
||||
-- filter
|
||||
AND ch.channel_class = 'Direct'
|
||||
AND co.country_iso_code = 'US'
|
||||
AND p.prod_category = 'Electronics'
|
||||
GROUP BY
|
||||
ch.channel_desc
|
||||
, co.country_iso_code
|
||||
, cu.cust_city
|
||||
, p.prod_category
|
||||
/
|
||||
/
|
||||
|
||||
@hash
|
||||
-- manually tuned query
|
||||
SELECT /*+ CARDINALITY(cu 55500) CARDINALITY(s 918000) */
|
||||
ch.channel_desc
|
||||
, co.country_iso_code co
|
||||
, cu.cust_city
|
||||
, p.prod_category
|
||||
, sum(s.quantity_sold)
|
||||
, sum(s.amount_sold)
|
||||
FROM
|
||||
sh.sales s
|
||||
, sh.customers cu
|
||||
, sh.countries co
|
||||
, sh.products p
|
||||
, sh.channels ch
|
||||
WHERE
|
||||
-- join
|
||||
s.cust_id = cu.cust_id
|
||||
AND cu.country_id = co.country_id
|
||||
AND s.prod_id = p.prod_id
|
||||
AND s.channel_id = ch.channel_id
|
||||
-- filter
|
||||
AND ch.channel_class = 'Direct'
|
||||
AND co.country_iso_code = 'US'
|
||||
AND p.prod_category = 'Electronics'
|
||||
GROUP BY
|
||||
ch.channel_desc
|
||||
, co.country_iso_code
|
||||
, cu.cust_city
|
||||
, p.prod_category
|
||||
/
|
||||
/
|
||||
|
||||
@hash
|
||||
|
||||
|
||||
|
||||
-- orig: 2689079980 1ka5g0kh4h6pc 0
|
||||
-- tuned: 3053916470 1fzf3vqv0f49q 0
|
||||
|
||||
-- workaround bug: Bug 5454975 : ORA-3113 WHEN EXECUTING DBMS_OUTLN.CREATE_OUTLINE
|
||||
ALTER SESSION SET create_stored_outlines = TRUE;
|
||||
-- make sure you use right SQL hash values and child cursor numbers here!
|
||||
EXEC DBMS_OUTLN.CREATE_OUTLINE(2689079980, 0, 'TEMP_SWAP_OUTLINE_BAD');
|
||||
EXEC DBMS_OUTLN.CREATE_OUTLINE(3053916470, 0, 'TEMP_SWAP_OUTLINE_GOOD');
|
||||
ALTER SESSION SET create_stored_outlines = FALSE;
|
||||
|
||||
COL outline_name_bad NEW_VALUE outline_name_bad
|
||||
COL outline_name_good NEW_VALUE outline_name_good
|
||||
|
||||
-- get outline names
|
||||
SELECT category,name outline_name_bad,owner,signature,enabled,timestamp,version FROM dba_outlines WHERE category = 'TEMP_SWAP_OUTLINE_BAD';
|
||||
SELECT category,name outline_name_good,owner,signature,enabled,timestamp,version FROM dba_outlines WHERE category = 'TEMP_SWAP_OUTLINE_GOOD';
|
||||
|
||||
-- change the outlines to the same category for modification
|
||||
ALTER OUTLINE &outline_name_bad CHANGE CATEGORY TO temp_swap_outline;
|
||||
ALTER OUTLINE &outline_name_good CHANGE CATEGORY TO temp_swap_outline;
|
||||
|
||||
CREATE PRIVATE OUTLINE bad FROM &outline_name_bad;
|
||||
CREATE PRIVATE OUTLINE good FROM &outline_name_good;
|
||||
|
||||
-- these ol$ and ol$hints tables are actually just GTTs (private to your session - private outlines)
|
||||
-- do NOT modify the real ol$ and ol$hints tables in OUTLN schema directly!!!
|
||||
SAVEPOINT before_ol_update;
|
||||
UPDATE ol$ SET hintcount=(SELECT hintcount FROM ol$ WHERE ol_name='GOOD') where ol_name='BAD';
|
||||
DELETE FROM ol$ WHERE ol_name='GOOD';
|
||||
DELETE FROM ol$hints WHERE ol_name='BAD';
|
||||
UPDATE ol$hints SET ol_name='BAD' where ol_name='GOOD';
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- this just invalidate outline
|
||||
EXEC DBMS_OUTLN_EDIT.REFRESH_PRIVATE_OUTLINE('BAD');
|
||||
|
||||
ALTER SESSION SET use_private_outlines = TRUE;
|
||||
-- run the original query again now - it should show "outline "BAD" used for this statement
|
||||
-- ...
|
||||
ALTER SESSION SET use_private_outlines = FALSE;
|
||||
|
||||
-- now publish the outline for use by others:
|
||||
CREATE OR REPLACE OUTLINE &outline_name_bad FROM PRIVATE bad FOR CATEGORY temp_swap_outline;
|
||||
ALTER SESSION SET use_stored_outlines = temp_swap_outline;
|
||||
-- run the query again, it should show the original production outline used, but with the new plan ...
|
||||
|
||||
-- change the outline to DEFAULT category so that any session with use_stored_outlines = TRUE would use it
|
||||
ALTER OUTLINE &outline_name_bad CHANGE CATEGORY TO "DEFAULT";
|
||||
ALTER SESSION SET use_stored_outlines = TRUE;
|
||||
-- optional...
|
||||
ALTER OUTLINE &outline_name_bad RENAME TO outline_1ka5g0kh4h6pc;
|
||||
|
||||
SELECT
|
||||
ch.channel_desc
|
||||
, co.country_iso_code co
|
||||
, cu.cust_city
|
||||
, p.prod_category
|
||||
, sum(s.quantity_sold)
|
||||
, sum(s.amount_sold)
|
||||
FROM
|
||||
sh.sales s
|
||||
, sh.customers cu
|
||||
, sh.countries co
|
||||
, sh.products p
|
||||
, sh.channels ch
|
||||
WHERE
|
||||
-- join
|
||||
s.cust_id = cu.cust_id
|
||||
AND cu.country_id = co.country_id
|
||||
AND s.prod_id = p.prod_id
|
||||
AND s.channel_id = ch.channel_id
|
||||
-- filter
|
||||
AND ch.channel_class = 'Direct'
|
||||
AND co.country_iso_code = 'US'
|
||||
AND p.prod_category = 'Electronics'
|
||||
GROUP BY
|
||||
ch.channel_desc
|
||||
, co.country_iso_code
|
||||
, cu.cust_city
|
||||
, p.prod_category
|
||||
/
|
||||
@x
|
||||
|
||||
|
||||
23
tpt/ast/02_qt_troubleshooting.sql
Normal file
23
tpt/ast/02_qt_troubleshooting.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
drop table qt_test;
|
||||
|
||||
create table qt_test (
|
||||
id number primary key
|
||||
, name varchar2(100)
|
||||
)
|
||||
/
|
||||
|
||||
insert into qt_test select rownum, lpad('x',100,'x') from dual connect by level <=10000;
|
||||
|
||||
exec dbms_stats.gather_table_stats(user,'QT_TEST');
|
||||
|
||||
select count(name) from qt_test;
|
||||
@x
|
||||
|
||||
alter table qt_test modify name not null;
|
||||
|
||||
select count(name) from qt_test;
|
||||
@x
|
||||
|
||||
34
tpt/ast/02_sql_plan_baseline_from_cursor.sql
Normal file
34
tpt/ast/02_sql_plan_baseline_from_cursor.sql
Normal file
@@ -0,0 +1,34 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
-- SQL Plan Baselines - DBMS_SPM in EE licenses - see http://jonathanlewis.wordpress.com/2011/01/12/fake-baselines/
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
-- bad_sqlid = 1ka5g0kh4h6pc
|
||||
-- good_sqlid = 1fzf3vqv0f49q
|
||||
|
||||
-- 1) Make sure your "bad query" is in library cache
|
||||
-- 2) Manually optimize the query with hints, params, etc to get the plan you want (the "good query")
|
||||
|
||||
-- 3) Create a disabled plan baseline for the "bad query":
|
||||
|
||||
VAR x NUMBER
|
||||
EXEC :x:= DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE('&bad_sqlid', enabled=>'NO');
|
||||
|
||||
-- 4) Find the SQL handle of your "bad" query:
|
||||
|
||||
SELECT sql_handle FROM dba_sql_plan_baselines WHERE sql_text = '<your sql_text>';
|
||||
|
||||
-- 5) Associate the "good query" plan with the "bad query" SQL plan baseline:
|
||||
|
||||
DEF good_sql_id = 1fzf3vqv0f49q
|
||||
DEF good_plan_hash_value = 2863714589
|
||||
DEF sql_handle_for_original = SQL_4b3ef772af37954d
|
||||
|
||||
VAR x NUMBER
|
||||
|
||||
exec :x := dbms_spm.load_plans_from_cursor_cache( -
|
||||
sql_id => '&good_sql_id', -
|
||||
plan_hash_value => &good_plan_hash_value, -
|
||||
sql_handle => '&sql_handle_for_original');
|
||||
|
||||
44
tpt/ast/02_sqlprofile_force_plan_with_custom_hints.sql
Normal file
44
tpt/ast/02_sqlprofile_force_plan_with_custom_hints.sql
Normal file
@@ -0,0 +1,44 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- use the @ast/02_choosing_join_order.sql script to run the demo query
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
-- SQL Profiles (require Tuning + Diag Pack):
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- Drop the profile:
|
||||
-- EXEC DBMS_SQLTUNE.DROP_SQL_PROFILE('MANUAL_PROFILE_1ka5g0kh4h6pc');
|
||||
|
||||
VAR sql_fulltext CLOB
|
||||
EXEC SELECT sql_fulltext INTO :sql_fulltext FROM v$sql WHERE sql_id = '1ka5g0kh4h6pc' AND rownum = 1;
|
||||
|
||||
-- Example 1: Set Join order:
|
||||
EXEC DBMS_SQLTUNE.IMPORT_SQL_PROFILE(sql_text=>:sql_fulltext, profile=>sys.sqlprof_attr('LEADING(@"SEL$1" "CO"@"SEL$1" "CH"@"SEL$1" "CU"@"SEL$1" "S"@"SEL$1" "P"@"SEL$1")'), name=> 'MANUAL_PROFILE_1ka5g0kh4h6pc');
|
||||
|
||||
-- Example 2: Adjust cardinality:
|
||||
EXEC DBMS_SQLTUNE.IMPORT_SQL_PROFILE(sql_text=>:sql_fulltext, profile=>sys.sqlprof_attr('OPT_ESTIMATE(@"SEL$1", TABLE, "CU"@"SEL$1", SCALE_ROWS=100000)'), name=> 'MANUAL_PROFILE_1ka5g0kh4h6pc');
|
||||
|
||||
-- Example 3: Set multiple hints:
|
||||
DECLARE
|
||||
hints sys.sqlprof_attr := sys.sqlprof_attr(
|
||||
('LEADING(@"SEL$1" "CO"@"SEL$1" "CH"@"SEL$1")')
|
||||
, ('OPT_ESTIMATE(@"SEL$1", TABLE, "CU"@"SEL$1", SCALE_ROWS=100000)')
|
||||
);
|
||||
BEGIN
|
||||
DBMS_SQLTUNE.IMPORT_SQL_PROFILE(sql_text=>:sql_fulltext, profile=> hints, name=> 'MANUAL_PROFILE_1ka5g0kh4h6pc');
|
||||
END;
|
||||
/
|
||||
|
||||
-- Example 4: SwingBench TPCDS-Like Query 31 skip scan issue (force match)
|
||||
-- alternative option would be to use opt_param('_optimizer_skip_scan_enabled','false')
|
||||
|
||||
DECLARE
|
||||
hints sys.sqlprof_attr := sys.sqlprof_attr(
|
||||
('NO_INDEX_SS(@"SEL$26CA4453" "STORE_SALES"@"SEL$1")')
|
||||
, ('NO_INDEX_SS(@"SEL$2C2C13D8" "WEB_SALES"@"SEL$2")')
|
||||
);
|
||||
BEGIN
|
||||
DBMS_SQLTUNE.IMPORT_SQL_PROFILE(sql_text=>:sql_fulltext, profile=> hints, name=> 'QUERY31_DISABLE_SKIP_SCAN', force_match=> TRUE);
|
||||
END;
|
||||
/
|
||||
|
||||
36
tpt/ast/03_bitmap_star_transformation.sql
Normal file
36
tpt/ast/03_bitmap_star_transformation.sql
Normal file
@@ -0,0 +1,36 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- setting the 11.2 cardinality feedback option to false for demo stability purposes
|
||||
exec execute immediate 'alter session set "_optimizer_use_feedback"=false'; exception when others then null;
|
||||
|
||||
SELECT /*+ star_transformation */
|
||||
ch.channel_desc
|
||||
, co.country_iso_code co
|
||||
, cu.cust_city
|
||||
, p.prod_category
|
||||
, sum(s.quantity_sold)
|
||||
, sum(s.amount_sold)
|
||||
FROM
|
||||
sh.sales s
|
||||
, sh.customers cu
|
||||
, sh.countries co
|
||||
, sh.products p
|
||||
, sh.channels ch
|
||||
WHERE
|
||||
-- join
|
||||
s.cust_id = cu.cust_id
|
||||
AND cu.country_id = co.country_id
|
||||
AND s.prod_id = p.prod_id
|
||||
AND s.channel_id = ch.channel_id
|
||||
-- filter
|
||||
AND ch.channel_class = 'Direct'
|
||||
AND co.country_iso_code = 'US'
|
||||
AND p.prod_category = 'Electronics'
|
||||
GROUP BY
|
||||
ch.channel_desc
|
||||
, co.country_iso_code
|
||||
, cu.cust_city
|
||||
, p.prod_category
|
||||
/
|
||||
|
||||
46
tpt/ast/03_constraints_not_null.sql
Normal file
46
tpt/ast/03_constraints_not_null.sql
Normal file
@@ -0,0 +1,46 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
DROP TABLE cons_demo;
|
||||
|
||||
CREATE TABLE cons_demo (owner varchar2(100), object_name varchar2(128));
|
||||
|
||||
INSERT /*+ APPEND */ INTO cons_demo SELECT owner, object_name FROM dba_objects;
|
||||
COMMIT;
|
||||
|
||||
SELECT COUNT(*) FROM cons_demo;
|
||||
@x
|
||||
|
||||
CREATE INDEX idx1_cons_demo ON cons_demo(owner);
|
||||
|
||||
SELECT COUNT(*) FROM cons_demo;
|
||||
@x
|
||||
|
||||
SELECT /*+ INDEX(cons_demo cons_demo(owner)) */ COUNT(*) FROM cons_demo;
|
||||
|
||||
ALTER TABLE cons_demo MODIFY owner NOT NULL NOVALIDATE;
|
||||
|
||||
INSERT INTO cons_demo VALUES (null, 'x');
|
||||
|
||||
SELECT COUNT(*) FROM cons_demo;
|
||||
@x
|
||||
|
||||
ALTER TABLE cons_demo MODIFY owner NULL;
|
||||
--ALTER TABLE cons_demo MODIFY owner NOT NULL VALIDATE;
|
||||
--ALTER TABLE cons_demo MODIFY owner NOT NULL DEFERRABLE INITIALLY DEFERRED VALIDATE;
|
||||
ALTER TABLE cons_demo MODIFY owner NOT NULL DEFERRABLE VALIDATE;
|
||||
|
||||
SELECT COUNT(*) FROM cons_demo;
|
||||
@x
|
||||
|
||||
|
||||
DROP TABLE cons_demo2;
|
||||
|
||||
CREATE TABLE cons_demo2 AS SELECT * FROM scott.emp;
|
||||
|
||||
ALTER TABLE cons_demo2 ADD CONSTRAINT c2 CHECK (SAL > 500);
|
||||
|
||||
SELECT * FROM cons_demo2 WHERE sal = 100;
|
||||
|
||||
@x
|
||||
|
||||
43
tpt/ast/03_index_density.sql
Normal file
43
tpt/ast/03_index_density.sql
Normal file
@@ -0,0 +1,43 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- analyze index density (how many rows per leaf block)
|
||||
-- using SYS_OP_LBID function
|
||||
|
||||
-- replace the first argument of SYS_OP_LBID number with the object_id of the index you are scanning
|
||||
-- also you need to modify the table name and index name hint to query the table/index of your interest
|
||||
-- make sure that the index is actually accessed in the execution plan (both fast full scan and range/full
|
||||
-- scans do work, but fast full scan is the fastest if you want to scan through the entire index segment)
|
||||
--
|
||||
-- additionally, you can use SAMPLE BLOCK syntax (below) to sample only some index blocks (when using
|
||||
-- fast full scan)
|
||||
|
||||
|
||||
COL blocks_histogram HEAD "Log(2,blocks) Histogram" FOR A30
|
||||
|
||||
SELECT
|
||||
LPAD(NVL(TO_CHAR(rows_per_block), 'Total:'), 15, ' ') num_rows_in_blk
|
||||
, blocks
|
||||
, NVL2(rows_per_block, LPAD('#', LOG(2,blocks), '#'), null) blocks_histogram
|
||||
FROM (
|
||||
SELECT
|
||||
CEIL(num_rows/10) * 10 rows_per_block
|
||||
, COUNT(*) blocks
|
||||
FROM (
|
||||
SELECT /*+ INDEX_FFS(o IDX3_INDEXED_OBJECTS) */
|
||||
count(*) num_rows
|
||||
FROM
|
||||
indexed_objects o -- SAMPLE BLOCK (1000) o
|
||||
WHERE
|
||||
owner IS NOT NULL
|
||||
GROUP BY
|
||||
SYS_OP_LBID( 78363, 'L', o.ROWID)
|
||||
)
|
||||
GROUP BY ROLLUP
|
||||
( CEIL(num_rows/10) * 10 )
|
||||
ORDER BY
|
||||
CEIL(num_rows/10) * 10
|
||||
)
|
||||
/
|
||||
|
||||
|
||||
20
tpt/ast/03_index_inefficiency_1.sql
Normal file
20
tpt/ast/03_index_inefficiency_1.sql
Normal file
@@ -0,0 +1,20 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
select /*+ index_rs(o o(owner)) */ avg(sysdate - created) days_old
|
||||
from
|
||||
indexed_objects o
|
||||
where
|
||||
owner = 'SYS'
|
||||
and object_type = 'PACKAGE'
|
||||
/
|
||||
|
||||
@x
|
||||
|
||||
-- Then create an index which satisfies the additional filter column...
|
||||
-- create index idx2_indexed_objects on indexed_objects (owner, object_type);
|
||||
|
||||
-- Then re-create the index with also the column that includes the columns selected in the query
|
||||
-- drop index idx2_indexed_objects;
|
||||
-- create index idx2_indexed_objects on indexed_objects (owner, object_type, created);
|
||||
|
||||
22
tpt/ast/03_index_skip_scan.sql
Normal file
22
tpt/ast/03_index_skip_scan.sql
Normal file
@@ -0,0 +1,22 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
DROP TABLE t;
|
||||
CREATE TABLE t AS SELECT * FROM dba_objects;
|
||||
CREATE INDEX i1 ON t(MOD(object_id,4), object_id);
|
||||
@gts t
|
||||
|
||||
SELECT /*+ INDEX_SS(t) */ * FROM t WHERE object_id = 12345;
|
||||
@x
|
||||
|
||||
CREATE INDEX i2 ON t(MOD(SYS_CONTEXT('USERENV','SID'),4), object_id);
|
||||
SELECT /*+ INDEX_SS(t) */ * FROM t WHERE object_id = 12345;
|
||||
@x
|
||||
|
||||
ALTER TABLE t ADD x NUMBER NULL;
|
||||
ALTER TABLE t MODIFY x DEFAULT MOD(SYS_CONTEXT('USERENV','SID'),16);
|
||||
|
||||
CREATE INDEX i3 ON t(x,object_id);
|
||||
SELECT * FROM t WHERE object_id = 12345;
|
||||
@x
|
||||
|
||||
26
tpt/ast/03_index_supporting_sorts.sql
Normal file
26
tpt/ast/03_index_supporting_sorts.sql
Normal file
@@ -0,0 +1,26 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
select
|
||||
owner, object_type, status, count(*)
|
||||
from
|
||||
indexed_objects o
|
||||
where
|
||||
owner = 'SYS'
|
||||
and object_type = 'JAVA CLASS'
|
||||
and created > sysdate - 3650
|
||||
group by
|
||||
owner,object_type,status
|
||||
order by
|
||||
status
|
||||
/
|
||||
|
||||
|
||||
-- Then re-create the index with also the column that we sort/group by
|
||||
-- drop index idx2_indexed_objects;
|
||||
-- create index idx2_indexed_objects on indexed_objects (owner, object_type, created, status);
|
||||
|
||||
-- And try tho swap the last 2 columns in end of the index:
|
||||
-- drop index idx2_indexed_objects;
|
||||
-- create index idx2_indexed_objects on indexed_objects (owner, object_type, status, created);
|
||||
|
||||
15
tpt/ast/04_cbo_selectivity_decay.sql
Normal file
15
tpt/ast/04_cbo_selectivity_decay.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
DROP TABLE selectivity_test;
|
||||
|
||||
CREATE TABLE selectivity_test AS
|
||||
SELECT sysdate - rownum d
|
||||
FROM dual connect by level <= 365;
|
||||
|
||||
@gts selectivity_test
|
||||
|
||||
@minmax d selectivity_test
|
||||
|
||||
@descxx selectivity_test
|
||||
|
||||
45
tpt/ast/04_cbo_troubleshoot_1.sql
Normal file
45
tpt/ast/04_cbo_troubleshoot_1.sql
Normal file
@@ -0,0 +1,45 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
SELECT /*+ opt_param('_optimizer_use_feedback', 'false') */
|
||||
d.department_name
|
||||
, e.first_name
|
||||
, e.last_name
|
||||
, prod.product_name
|
||||
, c.cust_first_name
|
||||
, c.cust_last_name
|
||||
, SUM(oi.quantity)
|
||||
, sum(oi.unit_price * oi.quantity) total_price
|
||||
FROM
|
||||
oe.orders o
|
||||
, oe.order_items oi
|
||||
, oe.products prod
|
||||
, oe.customers c
|
||||
, oe.promotions prom
|
||||
, hr.employees e
|
||||
, hr.departments d
|
||||
WHERE
|
||||
-- joins
|
||||
o.order_id = oi.order_id
|
||||
AND oi.product_id = prod.product_id
|
||||
AND o.promotion_id = prom.promo_id (+)
|
||||
AND o.customer_id = c.customer_id
|
||||
AND o.sales_rep_id = e.employee_id
|
||||
AND d.department_id = e.department_id
|
||||
-- filters
|
||||
AND d.department_name = 'Sales'
|
||||
AND e.first_name = 'William'
|
||||
AND e.last_name = 'Smith'
|
||||
AND prod.product_name = 'Mobile Web Phone'
|
||||
AND c.cust_first_name = 'Gena'
|
||||
AND c.cust_last_name = 'Harris'
|
||||
GROUP BY
|
||||
d.department_name
|
||||
, e.first_name
|
||||
, e.last_name
|
||||
, prod.product_name
|
||||
, c.cust_first_name
|
||||
, c.cust_last_name
|
||||
ORDER BY
|
||||
total_price
|
||||
/
|
||||
53
tpt/ast/04_cbo_troubleshoot_2.sql
Normal file
53
tpt/ast/04_cbo_troubleshoot_2.sql
Normal file
@@ -0,0 +1,53 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
SELECT /*+ leading (dep e o c oi)
|
||||
use_hash(oi)
|
||||
xuse_nl(oi)
|
||||
xindex(oi iii)
|
||||
NO_SWAP_JOIN_INPUTS(@"SEL$4B12EFE6" "C"@"SEL$1")
|
||||
NO_SWAP_JOIN_INPUTS(@"SEL$5488CC2B" "C"@"MAIN")
|
||||
opt_param('_optimizer_use_feedback', 'false')
|
||||
qb_name(main)
|
||||
*/
|
||||
dep.department_name
|
||||
, e.first_name
|
||||
, e.last_name
|
||||
, prod.product_name
|
||||
, c.cust_first_name
|
||||
, c.cust_last_name
|
||||
, SUM(oi.quantity)
|
||||
, sum(oi.unit_price * oi.quantity) total_price
|
||||
FROM
|
||||
hr.departments dep -- 1
|
||||
, hr.employees e -- 1
|
||||
, oe.orders o -- ?
|
||||
, oe.order_items oi -- ?
|
||||
, oe.products prod -- 1
|
||||
, oe.customers c -- 1
|
||||
, oe.promotions prom -- ?
|
||||
WHERE
|
||||
-- joins
|
||||
o.order_id = oi.order_id
|
||||
AND oi.product_id = prod.product_id
|
||||
AND o.promotion_id = prom.promo_id (+)
|
||||
AND o.customer_id = c.customer_id
|
||||
AND o.sales_rep_id = e.employee_id
|
||||
AND dep.department_id = e.department_id
|
||||
-- filters
|
||||
AND dep.department_name = 'Sales' -- 1 row
|
||||
AND e.first_name = 'William' -- 1 row
|
||||
AND e.last_name = 'Smith'
|
||||
AND prod.product_name = 'Mobile Web Phone' -- 1 row (view)
|
||||
AND c.cust_first_name = 'Gena' --
|
||||
AND c.cust_last_name = 'Harris' -- 1 row
|
||||
GROUP BY
|
||||
dep.department_name
|
||||
, e.first_name
|
||||
, e.last_name
|
||||
, prod.product_name
|
||||
, c.cust_first_name
|
||||
, c.cust_last_name
|
||||
ORDER BY
|
||||
total_price
|
||||
/
|
||||
50
tpt/ast/04_cbo_troubleshoot_3.sql
Normal file
50
tpt/ast/04_cbo_troubleshoot_3.sql
Normal file
@@ -0,0 +1,50 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
SELECT /*+
|
||||
opt_param('_optimizer_use_feedback', 'false')
|
||||
cardinality(c o 50000)
|
||||
OPT_ESTIMATE(@"SEL$1", JOIN, ("C"@"SEL$1", "E"@"SEL$1" "D"@"SEL$1" "O"@SEL$1), SCALE_ROWS=100000)
|
||||
cardinality(c e d o 100000)
|
||||
*/
|
||||
dep.department_name
|
||||
, e.first_name
|
||||
, e.last_name
|
||||
, prod.product_name
|
||||
, c.cust_first_name
|
||||
, c.cust_last_name
|
||||
, SUM(oi.quantity)
|
||||
, sum(oi.unit_price * oi.quantity) total_price
|
||||
FROM
|
||||
hr.departments dep -- 1
|
||||
, hr.employees e -- 1
|
||||
, oe.orders o -- ?
|
||||
, oe.order_items oi -- ?
|
||||
, oe.products prod -- 1
|
||||
, oe.customers c -- 1
|
||||
, oe.promotions prom -- ?
|
||||
WHERE
|
||||
-- joins
|
||||
o.order_id = oi.order_id
|
||||
AND oi.product_id = prod.product_id
|
||||
AND o.promotion_id = prom.promo_id (+)
|
||||
AND o.customer_id = c.customer_id
|
||||
AND o.sales_rep_id = e.employee_id
|
||||
AND dep.department_id = e.department_id
|
||||
-- filters
|
||||
AND dep.department_name = 'Sales' -- 1 row
|
||||
AND e.first_name = 'William' -- 1 row
|
||||
AND e.last_name = 'Smith'
|
||||
AND prod.product_name = 'Mobile Web Phone' -- 1 row (view)
|
||||
AND c.cust_first_name = 'Gena' --
|
||||
AND c.cust_last_name = 'Harris' -- 1 row
|
||||
GROUP BY
|
||||
dep.department_name
|
||||
, e.first_name
|
||||
, e.last_name
|
||||
, prod.product_name
|
||||
, c.cust_first_name
|
||||
, c.cust_last_name
|
||||
ORDER BY
|
||||
total_price
|
||||
/
|
||||
61
tpt/ast/04_cbo_troubleshoot_denormalized.sql
Normal file
61
tpt/ast/04_cbo_troubleshoot_denormalized.sql
Normal file
@@ -0,0 +1,61 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
SELECT
|
||||
/*+ opt_param('_optimizer_use_feedback', 'false')
|
||||
dynamic_sampling(4) opt_param('_optimizer_use_feedback', 'false')
|
||||
leading(c d e o oi)
|
||||
use_hash(o)
|
||||
use_hash(oi)
|
||||
index(o)
|
||||
index(oi)
|
||||
NO_SWAP_JOIN_INPUTS(@"SEL$4B12EFE6" "I"@"SEL$2")
|
||||
NO_SWAP_JOIN_INPUTS(@"SEL$4B12EFE6" "D"@"SEL$2")
|
||||
*/
|
||||
d.department_name
|
||||
, e.first_name
|
||||
, e.last_name
|
||||
, prod.product_name
|
||||
, c.cust_first_name
|
||||
, c.cust_last_name
|
||||
, SUM(oi.quantity)
|
||||
, sum(oi.unit_price * oi.quantity) total_price
|
||||
FROM
|
||||
oe.orders o
|
||||
, oe.order_items oi
|
||||
, oe.products prod
|
||||
, oe.customers c
|
||||
, oe.promotions prom
|
||||
, hr.employees e
|
||||
, hr.departments d
|
||||
WHERE
|
||||
-- joins
|
||||
o.order_id = oi.order_id
|
||||
AND oi.product_id = prod.product_id
|
||||
AND o.promotion_id = prom.promo_id (+)
|
||||
AND o.customer_id = c.customer_id
|
||||
AND o.sales_rep_id = e.employee_id
|
||||
AND d.department_id = e.department_id
|
||||
-- filters
|
||||
AND d.department_name = 'Sales'
|
||||
AND e.first_name = 'William'
|
||||
AND e.last_name = 'Smith'
|
||||
AND prod.product_name = 'Mobile Web Phone'
|
||||
AND c.cust_first_name = 'Gena'
|
||||
AND c.cust_last_name = 'Harris'
|
||||
AND o.customer_id = 189 -- (select customer_id from oe.customers c2
|
||||
-- WHERE c2.cust_first_name = 'Gena'
|
||||
-- AND c2.cust_last_name = 'Harris')
|
||||
AND oi.customer_id = 189 -- (select customer_id from oe.customers c3
|
||||
-- WHERE c3.cust_first_name = 'Gena'
|
||||
-- AND c3.cust_last_name = 'Harris')
|
||||
GROUP BY
|
||||
d.department_name
|
||||
, e.first_name
|
||||
, e.last_name
|
||||
, prod.product_name
|
||||
, c.cust_first_name
|
||||
, c.cust_last_name
|
||||
ORDER BY
|
||||
total_price
|
||||
/
|
||||
49
tpt/ast/04_cbo_troubleshoot_save.sql
Normal file
49
tpt/ast/04_cbo_troubleshoot_save.sql
Normal file
@@ -0,0 +1,49 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
SELECT /*+ leading (dep e o)
|
||||
NO_SWAP_JOIN_INPUTS(@"SEL$5488CC2B" "C"@"MAIN")
|
||||
opt_param('_optimizer_use_feedback', 'false')
|
||||
qb_name(main)
|
||||
*/
|
||||
dep.department_name
|
||||
, e.first_name
|
||||
, e.last_name
|
||||
, prod.product_name
|
||||
, c.cust_first_name
|
||||
, c.cust_last_name
|
||||
, SUM(oi.quantity)
|
||||
, sum(oi.unit_price * oi.quantity) total_price
|
||||
FROM
|
||||
hr.departments dep -- 1
|
||||
, hr.employees e -- 1
|
||||
, oe.orders o -- ?
|
||||
, oe.order_items oi -- ?
|
||||
, oe.products prod -- 1
|
||||
, oe.customers c -- 1
|
||||
, oe.promotions prom -- ?
|
||||
WHERE
|
||||
-- joins
|
||||
o.order_id = oi.order_id
|
||||
AND oi.product_id = prod.product_id
|
||||
AND o.promotion_id = prom.promo_id (+)
|
||||
AND o.customer_id = c.customer_id
|
||||
AND o.sales_rep_id = e.employee_id
|
||||
AND dep.department_id = e.department_id
|
||||
-- filters
|
||||
AND dep.department_name = 'Sales' -- 1 row
|
||||
AND e.first_name = 'William' -- 1 row
|
||||
AND e.last_name = 'Smith'
|
||||
AND prod.product_name = 'Mobile Web Phone' -- 1 row (view)
|
||||
AND c.cust_first_name = 'Gena' --
|
||||
AND c.cust_last_name = 'Harris' -- 1 row
|
||||
GROUP BY
|
||||
dep.department_name
|
||||
, e.first_name
|
||||
, e.last_name
|
||||
, prod.product_name
|
||||
, c.cust_first_name
|
||||
, c.cust_last_name
|
||||
ORDER BY
|
||||
total_price
|
||||
/
|
||||
73
tpt/ast/04_cbo_troubleshoot_setup.sql
Normal file
73
tpt/ast/04_cbo_troubleshoot_setup.sql
Normal file
@@ -0,0 +1,73 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
INSERT INTO oe.promotions
|
||||
SELECT 10+rownum promo_id, 'promotion '||to_char(10+rownum)
|
||||
FROM dual CONNECT BY level < 90
|
||||
/
|
||||
|
||||
INSERT INTO oe.promotions VALUES (100, 'online super-sale');
|
||||
|
||||
exec dbms_stats.gather_schema_stats('OE');
|
||||
|
||||
exec dbms_stats.create_stat_table('OE', 'STATS_BACKUP');
|
||||
|
||||
exec dbms_stats.export_schema_stats('OE', 'STATS_BACKUP', 'AST_04_TROUBLE_01');
|
||||
|
||||
CREATE TABLE oe.tmp AS SELECT * FROM oe.orders WHERE 1=0;
|
||||
|
||||
INSERT /*+ APPEND */ INTO oe.tmp
|
||||
SELECT
|
||||
oe.orders_seq.NEXTVAL
|
||||
, sysdate -- order date
|
||||
, 'online' -- order mode
|
||||
, 189 -- customer id
|
||||
, 12 -- order status
|
||||
, 99.95 -- order_total
|
||||
, 171 -- sales rep
|
||||
, 100 -- promotion_id
|
||||
, null -- warehouse_id -- added new column
|
||||
FROM
|
||||
dual CONNECT BY level <= 100000
|
||||
/
|
||||
COMMIT;
|
||||
|
||||
INSERT INTO oe.orders (
|
||||
order_id NOT NULL NUMBER(12)
|
||||
, order_date NOT NULL TIMESTAMP(6) WITH LOCAL TIME ZONE
|
||||
, order_mode VARCHAR2(8)
|
||||
, customer_id NOT NULL NUMBER(6)
|
||||
, order_status NUMBER(2)
|
||||
, order_total NUMBER(8,2)
|
||||
, sales_rep_id NUMBER(6)
|
||||
, promotion_id
|
||||
, warehouse_id -- added a new column
|
||||
)
|
||||
SELECT * FROM oe.tmp
|
||||
ORDER BY
|
||||
dbms_random.random -- to increase pk clustering factor
|
||||
/
|
||||
|
||||
COMMIT;
|
||||
|
||||
BEGIN
|
||||
FOR i IN (SELECT order_id FROM oe.tmp) LOOP
|
||||
-- such a lousy loop is needed as there's a "single row" trigger on order_items tab
|
||||
INSERT INTO oe.order_items (ORDER_ID,PRODUCT_ID,UNIT_PRICE,QUANTITY)
|
||||
VALUES ( i.order_id, 3337, 9.95, power(2,power(2,dbms_random.value(1,3))) );
|
||||
-- commit in a loop so i wouldnt blow up my little undo tablespace
|
||||
COMMIT;
|
||||
END LOOP;
|
||||
END;
|
||||
/
|
||||
|
||||
-- save old "bad" stats
|
||||
exec dbms_stats.export_schema_stats('OE', 'STATS_BACKUP', 'AST_04_TROUBLE_BEGIN');
|
||||
-- to restore:
|
||||
-- exec dbms_stats.import_schema_stats('OE', 'STATS_BACKUP', 'AST_04_TROUBLE_BEGIN', NO_INVALIDATE=>FALSE);
|
||||
|
||||
-- run the 04_cbo_troubleshoot_1.sql and troubleshoot! :)
|
||||
|
||||
|
||||
|
||||
|
||||
25
tpt/ast/ast_setup.sql
Normal file
25
tpt/ast/ast_setup.sql
Normal file
@@ -0,0 +1,25 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
DEF datafile_dir=/export/home/oracle/oradata/SOL102
|
||||
|
||||
-- CREATE TABLESPACE ast DATAFILE '&datafile_dir/ast.01.dbf' SIZE 200M AUTOEXTEND ON;
|
||||
CREATE BIGFILE TABLESPACE ast DATAFILE SIZE 200M AUTOEXTEND ON;
|
||||
|
||||
CREATE USER ast IDENTIFIED BY ast DEFAULT TABLESPACE ast TEMPORARY TABLESPACE temp;
|
||||
|
||||
ALTER USER ast QUOTA UNLIMITED ON ast;
|
||||
|
||||
GRANT CREATE SESSION TO ast;
|
||||
GRANT CONNECT, RESOURCE TO ast;
|
||||
GRANT SELECT ANY DICTIONARY TO ast;
|
||||
|
||||
GRANT EXECUTE ON DBMS_LOCK TO ast;
|
||||
GRANT EXECUTE ON DBMS_MONITOR TO ast;
|
||||
|
||||
GRANT EXECUTE ON DBMS_SQLTUNE TO ast;
|
||||
GRANT EXECUTE ON DBMS_WORKLOAD_REPOSITORY TO ast;
|
||||
|
||||
-- for testing
|
||||
GRANT DBA TO ast;
|
||||
|
||||
85
tpt/ast/ast_setup_schema.sql
Normal file
85
tpt/ast/ast_setup_schema.sql
Normal file
@@ -0,0 +1,85 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
DROP TABLE test_objects;
|
||||
DROP TABLE test_objects10;
|
||||
DROP TABLE test_objects100;
|
||||
DROP TABLE test_users;
|
||||
DROP TABLE indexed_objects;
|
||||
DROP TABLE dummy1;
|
||||
DROP TABLE dummy2;
|
||||
DROP TABLE indexed_source;
|
||||
|
||||
CREATE TABLE test_objects AS SELECT * FROM dba_objects;
|
||||
CREATE TABLE test_objects10 AS SELECT * FROM test_objects WHERE rownum <= 10;
|
||||
CREATE TABLE test_objects100 AS SELECT * FROM test_objects WHERE rownum <= 100;
|
||||
CREATE TABLE test_users AS SELECT * FROM all_users;
|
||||
|
||||
CREATE TABLE indexed_objects AS SELECT * FROM dba_objects;
|
||||
CREATE UNIQUE INDEX pk_obj_id ON indexed_objects (object_id);
|
||||
CREATE INDEX idx_owner_name ON indexed_objects(owner,object_name);
|
||||
|
||||
CREATE TABLE dummy1 AS SELECT 1 a, 'one' b FROM dual;
|
||||
CREATE TABLE dummy2 AS SELECT 1 a, 'one' b FROM dual;
|
||||
|
||||
CREATE TABLE indexed_source AS SELECT * FROM dba_source;
|
||||
CREATE INDEX idx1_indexed_source ON indexed_source (owner,name,line);
|
||||
|
||||
|
||||
EXEC DBMS_STATS.SET_PARAM('METHOD_OPT', 'FOR ALL COLUMNS SIZE REPEAT');
|
||||
|
||||
--EXEC DBMS_STATS.GATHER_SCHEMA_STATS('AST');
|
||||
EXEC DBMS_STATS.GATHER_SCHEMA_STATS(user);
|
||||
|
||||
-- deterministic PL/SQL functions can utilize PL/SQL function result caching
|
||||
CREATE OR REPLACE FUNCTION my_multiply(a IN NUMBER, b IN NUMBER) RETURN NUMBER AS
|
||||
BEGIN
|
||||
DBMS_OUTPUT.PUT_LINE('x');
|
||||
RETURN a * b;
|
||||
END;
|
||||
/
|
||||
|
||||
CREATE OR REPLACE FUNCTION my_multiply_d (a IN NUMBER, b IN NUMBER) RETURN NUMBER
|
||||
DETERMINISTIC
|
||||
AS
|
||||
BEGIN
|
||||
RETURN a * b;
|
||||
END;
|
||||
/
|
||||
|
||||
CREATE OR REPLACE FUNCTION my_sqrt (a IN NUMBER) RETURN NUMBER
|
||||
AS
|
||||
BEGIN
|
||||
RETURN SQRT(a);
|
||||
END;
|
||||
/
|
||||
|
||||
-- select max(my_sqrt(mod(rownum,100))) from dual connect by level<=100000;
|
||||
CREATE OR REPLACE FUNCTION my_sqrt_d (a IN NUMBER) RETURN NUMBER
|
||||
DETERMINISTIC
|
||||
AS
|
||||
BEGIN
|
||||
RETURN SQRT(a);
|
||||
END;
|
||||
/
|
||||
|
||||
|
||||
|
||||
|
||||
-- additional stuff in scott and other standard demo schemas
|
||||
|
||||
create or replace view scott.high_pay_depts as
|
||||
select
|
||||
*
|
||||
from
|
||||
scott.dept d
|
||||
where
|
||||
exists (select 1
|
||||
from
|
||||
scott.emp e
|
||||
where
|
||||
e.deptno = d.deptno
|
||||
and e.sal > 4500
|
||||
)
|
||||
/
|
||||
|
||||
224
tpt/ast/execution_plan.txt
Normal file
224
tpt/ast/execution_plan.txt
Normal file
@@ -0,0 +1,224 @@
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
| 0 | SELECT STATEMENT | | | | 2121K(100)| | | |
|
||||
| 1 | SORT ORDER BY | | 3 | 6675 | 2121K (1)| 01:21:11 | | |
|
||||
|* 2 | HASH JOIN | | 3 | 6675 | 2121K (1)| 01:21:11 | | |
|
||||
|* 3 | HASH JOIN OUTER | | 1 | 2213 | 2121K (1)| 01:21:11 | | |
|
||||
| 4 | VIEW | | 1 | 2116 | 2121K (1)| 01:21:11 | | |
|
||||
| 5 | NESTED LOOPS OUTER | | 1 | 1306 | 2121K (1)| 01:21:11 | | |
|
||||
| 6 | NESTED LOOPS OUTER | | 1 | 1248 | 2121K (1)| 01:21:11 | | |
|
||||
| 7 | NESTED LOOPS | | 1 | 1190 | 2121K (1)| 01:21:11 | | |
|
||||
|* 8 | HASH JOIN | | 1 | 1090 | 2121K (1)| 01:21:11 | | |
|
||||
| 9 | VIEW | | 7 | 7329 | 2121K (1)| 01:21:11 | | |
|
||||
| 10 | UNION-ALL | | | | | | | |
|
||||
| 11 | NESTED LOOPS OUTER | | 1 | 648 | 31348 (2)| 00:01:12 | | |
|
||||
| 12 | NESTED LOOPS | | 1 | 613 | 31347 (2)| 00:01:12 | | |
|
||||
| 13 | NESTED LOOPS OUTER | | 1 | 513 | 31346 (2)| 00:01:12 | | |
|
||||
| 14 | NESTED LOOPS OUTER | | 1 | 475 | 31345 (2)| 00:01:12 | | |
|
||||
| 15 | NESTED LOOPS OUTER | | 1 | 412 | 31344 (2)| 00:01:12 | | |
|
||||
| 16 | NESTED LOOPS | | 1 | 312 | 31343 (2)| 00:01:12 | | |
|
||||
| 17 | VIEW | | 2 | 424 | 31341 (2)| 00:01:12 | | |
|
||||
| 18 | UNION-ALL | | | | | | | |
|
||||
| 19 | PARTITION LIST ITERATOR | | 1 | 100 | 18711 (1)| 00:00:43 | KEY | KEY |
|
||||
| 20 | INLIST ITERATOR | | | | | | | |
|
||||
|* 21 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_A | 1 | 100 | 18711 (1)| 00:00:43 | KEY | KEY |
|
||||
|* 22 | INDEX RANGE SCAN | TABLE_A_PK | 335K| | 3751 (2)| 00:00:09 | KEY | KEY |
|
||||
|* 23 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_B | 1 | 100 | 12628 (2)| 00:00:29 | 1 | 1 |
|
||||
| 24 | NESTED LOOPS | | 1 | 150 | 12630 (2)| 00:00:29 | | |
|
||||
| 25 | INLIST ITERATOR | | | | | | | |
|
||||
|* 26 | TABLE ACCESS BY INDEX ROWID | TABLE_C | 1 | 50 | 1 (0)| 00:00:01 | | |
|
||||
|* 27 | INDEX RANGE SCAN | TABLE_C_PK | 3 | | 1 (0)| 00:00:01 | | |
|
||||
| 28 | PARTITION RANGE INLIST | | 36582 | | 6799 (4)| 00:00:16 | KEY(I | KEY(I |
|
||||
| 29 | PARTITION LIST ITERATOR | | 36582 | | 6799 (4)| 00:00:16 | KEY | KEY |
|
||||
|* 30 | INDEX RANGE SCAN | TABLE_D_PK | 36582 | | 6799 (4)| 00:00:16 | KEY(I | KEY(I |
|
||||
| 31 | PARTITION RANGE INLIST | | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 32 | INLIST ITERATOR | | | | | | | |
|
||||
| 33 | PARTITION LIST ITERATOR | | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
|* 34 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_E | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
|* 35 | INDEX RANGE SCAN | TABLE_E_PK | 1 | | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 36 | PARTITION RANGE ITERATOR | | 1 | 100 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 37 | PARTITION LIST ITERATOR | | 1 | 100 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 38 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_F | 1 | 100 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|* 39 | INDEX UNIQUE SCAN | TABLE_F_PK | 1 | | 0 (0)| | KEY | KEY |
|
||||
| 40 | PARTITION RANGE ITERATOR | | 1 | 63 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 41 | PARTITION LIST ITERATOR | | 1 | 63 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 42 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_G | 1 | 63 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|* 43 | INDEX UNIQUE SCAN | TABLE_G_PK | 1 | | 0 (0)| | KEY | KEY |
|
||||
| 44 | PARTITION RANGE ITERATOR | | 1 | 38 | 0 (0)| | KEY | KEY |
|
||||
| 45 | PARTITION LIST ITERATOR | | 1 | 38 | 0 (0)| | KEY | KEY |
|
||||
|* 46 | INDEX UNIQUE SCAN | TABLE_H_PK | 1 | 38 | 0 (0)| | KEY | KEY |
|
||||
| 47 | PARTITION RANGE ITERATOR | | 1 | 100 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|* 48 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_I | 1 | 100 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|* 49 | INDEX UNIQUE SCAN | TABLE_I_PK | 1 | | 0 (0)| | KEY | KEY |
|
||||
| 50 | PARTITION RANGE ITERATOR | | 1 | 35 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 51 | PARTITION LIST ITERATOR | | 1 | 35 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|* 52 | INDEX RANGE SCAN | TABLE_J_PK | 1 | 35 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 53 | VIEW | | 2 | 2076 | 2089K (1)| 01:19:58 | | |
|
||||
| 54 | UNION-ALL | | | | | | | |
|
||||
| 55 | NESTED LOOPS OUTER | | 1 | 547 | 4574 (91)| 00:00:11 | | |
|
||||
| 56 | NESTED LOOPS OUTER | | 1 | 447 | 4573 (91)| 00:00:11 | | |
|
||||
| 57 | NESTED LOOPS OUTER | | 1 | 430 | 4572 (91)| 00:00:11 | | |
|
||||
| 58 | NESTED LOOPS OUTER | | 1 | 413 | 4572 (91)| 00:00:11 | | |
|
||||
| 59 | NESTED LOOPS | | 1 | 396 | 4571 (91)| 00:00:11 | | |
|
||||
| 60 | NESTED LOOPS | | 1 | 300 | 4570 (91)| 00:00:11 | | |
|
||||
|* 61 | HASH JOIN | | 1 | 200 | 4569 (91)| 00:00:11 | | |
|
||||
| 62 | INLIST ITERATOR | | | | | | | |
|
||||
| 63 | PARTITION RANGE ITERATOR | | 1 | 100 | 156 (4)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 64 | INLIST ITERATOR | | | | | | | |
|
||||
| 65 | PARTITION LIST ITERATOR | | 1 | 100 | 156 (4)| 00:00:01 | KEY(I | KEY(I |
|
||||
|* 66 | TABLE ACCESS BY LOCAL INDEX ROWID| TABLE_E | 1 | 100 | 156 (4)| 00:00:01 | KEY(I | KEY(I |
|
||||
|* 67 | INDEX RANGE SCAN | TABLE_E_UQ | 37 | | 282 (5)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 68 | PARTITION LIST ALL | | 5 | 500 | 4411 (94)| 00:00:11 | 1 | 26 |
|
||||
|* 69 | TABLE ACCESS FULL | TABLE_A | 5 | 500 | 4411 (94)| 00:00:11 | 1 | 26 |
|
||||
| 70 | PARTITION RANGE INLIST | | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
|* 71 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_I | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
|* 72 | INDEX UNIQUE SCAN | TABLE_I_PK | 1 | | 0 (0)| | KEY(I | KEY(I |
|
||||
| 73 | TABLE ACCESS BY GLOBAL INDEX ROWID | TABLE_K | 1 | 96 | 1 (0)| 00:00:01 | ROW L | ROW L |
|
||||
|* 74 | INDEX UNIQUE SCAN | TABLE_K_PK | 1 | | 0 (0)| | | |
|
||||
| 75 | PARTITION RANGE ITERATOR | | 6 | 102 | 0 (0)| | KEY | KEY |
|
||||
|* 76 | INDEX UNIQUE SCAN | TABLE_I_PK | 6 | 102 | 0 (0)| | KEY | KEY |
|
||||
| 77 | PARTITION RANGE ITERATOR | | 6 | 102 | 4 (50)| 00:00:01 | KEY | KEY |
|
||||
|* 78 | INDEX FAST FULL SCAN | TABLE_I_PK | 6 | 102 | 4 (50)| 00:00:01 | KEY | KEY |
|
||||
| 79 | PARTITION RANGE ITERATOR | | 6 | 102 | 4 (50)| 00:00:01 | KEY | KEY |
|
||||
|* 80 | INDEX FAST FULL SCAN | TABLE_I_PK | 6 | 102 | 4 (50)| 00:00:01 | KEY | KEY |
|
||||
| 81 | PARTITION RANGE ITERATOR | | 1 | 100 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 82 | PARTITION LIST ITERATOR | | 1 | 100 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 83 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_L | 1 | 100 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|* 84 | INDEX UNIQUE SCAN | TABLE_L_PK | 1 | | 0 (0)| | KEY | KEY |
|
||||
| 85 | NESTED LOOPS OUTER | | 1 | 570 | 2085K (1)| 01:19:48 | | |
|
||||
| 86 | NESTED LOOPS OUTER | | 1 | 470 | 2085K (1)| 01:19:48 | | |
|
||||
| 87 | NESTED LOOPS OUTER | | 1 | 453 | 2085K (1)| 01:19:48 | | |
|
||||
| 88 | NESTED LOOPS OUTER | | 1 | 436 | 2085K (1)| 01:19:48 | | |
|
||||
| 89 | NESTED LOOPS | | 1 | 419 | 2085K (1)| 01:19:48 | | |
|
||||
| 90 | NESTED LOOPS | | 1 | 323 | 2085K (1)| 01:19:48 | | |
|
||||
| 91 | NESTED LOOPS | | 1 | 223 | 2085K (1)| 01:19:48 | | |
|
||||
| 92 | NESTED LOOPS | | 55 | 6765 | 2085K (1)| 01:19:48 | | |
|
||||
| 93 | INLIST ITERATOR | | | | | | | |
|
||||
|* 94 | INDEX RANGE SCAN | TABLE_C_PK | 89 | 2047 | 1 (0)| 00:00:01 | | |
|
||||
| 95 | INLIST ITERATOR | | | | | | | |
|
||||
| 96 | PARTITION RANGE ITERATOR | | 1 | 100 | 23427 (1)| 00:00:54 | KEY(I | KEY(I |
|
||||
| 97 | PARTITION LIST INLIST | | 1 | 100 | 23427 (1)| 00:00:54 | KEY(I | KEY(I |
|
||||
|* 98 | TABLE ACCESS BY LOCAL INDEX ROWID| TABLE_E | 1 | 100 | 23427 (1)| 00:00:54 | KEY(I | KEY(I |
|
||||
|* 99 | INDEX RANGE SCAN | TABLE_E_PK | 60462 | | 748 (8)| 00:00:02 | KEY(I | KEY(I |
|
||||
| 100 | PARTITION RANGE INLIST | | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 101 | PARTITION LIST ITERATOR | | 1 | 100 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|*102 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_B | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*103 | INDEX RANGE SCAN | TABLE_D_PK | 1 | | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 104 | PARTITION RANGE INLIST | | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*105 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_I | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*106 | INDEX UNIQUE SCAN | TABLE_I_PK | 1 | | 0 (0)| | KEY(I | KEY(I |
|
||||
| 107 | TABLE ACCESS BY GLOBAL INDEX ROWID | TABLE_K | 1 | 96 | 1 (0)| 00:00:01 | ROW L | ROW L |
|
||||
|*108 | INDEX UNIQUE SCAN | TABLE_K_PK | 1 | | 0 (0)| | | |
|
||||
| 109 | PARTITION RANGE ITERATOR | | 6 | 102 | 0 (0)| | KEY | KEY |
|
||||
|*110 | INDEX UNIQUE SCAN | TABLE_I_PK | 6 | 102 | 0 (0)| | KEY | KEY |
|
||||
| 111 | PARTITION RANGE ITERATOR | | 6 | 102 | 4 (50)| 00:00:01 | KEY | KEY |
|
||||
|*112 | INDEX FAST FULL SCAN | TABLE_I_PK | 6 | 102 | 4 (50)| 00:00:01 | KEY | KEY |
|
||||
| 113 | PARTITION RANGE ITERATOR | | 6 | 102 | 4 (50)| 00:00:01 | KEY | KEY |
|
||||
|*114 | INDEX FAST FULL SCAN | TABLE_I_PK | 6 | 102 | 4 (50)| 00:00:01 | KEY | KEY |
|
||||
| 115 | PARTITION RANGE ITERATOR | | 1 | 100 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 116 | PARTITION LIST ITERATOR | | 1 | 100 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 117 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_L | 1 | 100 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|*118 | INDEX UNIQUE SCAN | TABLE_L_PK | 1 | | 0 (0)| | KEY | KEY |
|
||||
| 119 | VIEW | | 2 | 2054 | 147 (2)| 00:00:01 | | |
|
||||
| 120 | UNION-ALL | | | | | | | |
|
||||
| 121 | NESTED LOOPS | | 1 | 362 | 74 (2)| 00:00:01 | | |
|
||||
| 122 | NESTED LOOPS | | 1 | 262 | 73 (2)| 00:00:01 | | |
|
||||
| 123 | NESTED LOOPS | | 1 | 200 | 72 (2)| 00:00:01 | | |
|
||||
| 124 | INLIST ITERATOR | | | | | | | |
|
||||
| 125 | PARTITION RANGE ITERATOR | | 1 | 100 | 71 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 126 | INLIST ITERATOR | | | | | | | |
|
||||
| 127 | PARTITION LIST ITERATOR | | 1 | 100 | 71 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*128 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_E | 1 | 100 | 71 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*129 | INDEX RANGE SCAN | TABLE_E_UQ | 6 | | 137 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 130 | PARTITION RANGE INLIST | | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 131 | PARTITION LIST ALL | | 1 | 100 | 1 (0)| 00:00:01 | 1 | 9 |
|
||||
|*132 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_B | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*133 | INDEX RANGE SCAN | TABLE_D_PK | 1 | | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 134 | TABLE ACCESS BY GLOBAL INDEX ROWID | TABLE_K | 1 | 62 | 1 (0)| 00:00:01 | ROW L | ROW L |
|
||||
|*135 | INDEX UNIQUE SCAN | TABLE_K_PK | 1 | | 0 (0)| | | |
|
||||
| 136 | PARTITION RANGE INLIST | | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*137 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_I | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*138 | INDEX UNIQUE SCAN | TABLE_I_PK | 1 | | 0 (0)| | KEY(I | KEY(I |
|
||||
|*139 | FILTER | | | | | | | |
|
||||
|*140 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_B | 1 | 100 | 1 (0)| 00:00:01 | 1 | 1 |
|
||||
| 141 | NESTED LOOPS | | 1 | 200 | 72 (2)| 00:00:01 | | |
|
||||
| 142 | INLIST ITERATOR | | | | | | | |
|
||||
| 143 | PARTITION RANGE ITERATOR | | 1 | 100 | 71 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 144 | INLIST ITERATOR | | | | | | | |
|
||||
| 145 | PARTITION LIST ITERATOR | | 1 | 100 | 71 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*146 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_E | 1 | 100 | 71 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*147 | INDEX RANGE SCAN | TABLE_E_UQ | 6 | | 137 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 148 | PARTITION RANGE INLIST | | 1 | | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 149 | PARTITION LIST ALL | | 1 | | 1 (0)| 00:00:01 | 1 | 9 |
|
||||
|*150 | INDEX RANGE SCAN | TABLE_D_PK | 1 | | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 151 | NESTED LOOPS OUTER | | 1 | 426 | 76 (2)| 00:00:01 | | |
|
||||
| 152 | NESTED LOOPS | | 1 | 358 | 75 (2)| 00:00:01 | | |
|
||||
| 153 | NESTED LOOPS OUTER | | 1 | 313 | 74 (2)| 00:00:01 | | |
|
||||
| 154 | NESTED LOOPS OUTER | | 1 | 275 | 73 (2)| 00:00:01 | | |
|
||||
| 155 | NESTED LOOPS | | 1 | 200 | 72 (2)| 00:00:01 | | |
|
||||
| 156 | INLIST ITERATOR | | | | | | | |
|
||||
| 157 | PARTITION RANGE ITERATOR | | 1 | 100 | 71 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 158 | INLIST ITERATOR | | | | | | | |
|
||||
| 159 | PARTITION LIST ITERATOR | | 1 | 100 | 71 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*160 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_E | 1 | 100 | 71 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*161 | INDEX RANGE SCAN | TABLE_E_UQ | 6 | | 137 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 162 | PARTITION RANGE INLIST | | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 163 | PARTITION LIST SINGLE | | 1 | 100 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|*164 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_B | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*165 | INDEX RANGE SCAN | TABLE_D_PK | 1 | | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 166 | PARTITION RANGE ITERATOR | | 1 | 75 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 167 | PARTITION LIST ITERATOR | | 1 | 75 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 168 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_G | 1 | 75 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|*169 | INDEX UNIQUE SCAN | TABLE_G_PK | 1 | | 0 (0)| | KEY | KEY |
|
||||
| 170 | PARTITION RANGE ITERATOR | | 1 | 38 | 0 (0)| | KEY | KEY |
|
||||
| 171 | PARTITION LIST ITERATOR | | 1 | 38 | 0 (0)| | KEY | KEY |
|
||||
|*172 | INDEX UNIQUE SCAN | TABLE_H_PK | 1 | 38 | 0 (0)| | KEY | KEY |
|
||||
| 173 | PARTITION RANGE ITERATOR | | 1 | 45 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|*174 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_I | 1 | 45 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|*175 | INDEX UNIQUE SCAN | TABLE_I_PK | 1 | | 0 (0)| | KEY | KEY |
|
||||
| 176 | PARTITION RANGE ITERATOR | | 1 | 68 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 177 | PARTITION LIST SINGLE | | 1 | 68 | 1 (0)| 00:00:01 | | |
|
||||
| 178 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_F | 1 | 68 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|*179 | INDEX UNIQUE SCAN | TABLE_F_PK | 1 | | 0 (0)| | KEY | KEY |
|
||||
| 180 | NESTED LOOPS OUTER | | 1 | 423 | 76 (2)| 00:00:01 | | |
|
||||
| 181 | NESTED LOOPS | | 1 | 355 | 75 (2)| 00:00:01 | | |
|
||||
| 182 | NESTED LOOPS OUTER | | 1 | 310 | 74 (2)| 00:00:01 | | |
|
||||
| 183 | NESTED LOOPS OUTER | | 1 | 272 | 73 (2)| 00:00:01 | | |
|
||||
| 184 | NESTED LOOPS | | 1 | 200 | 72 (2)| 00:00:01 | | |
|
||||
| 185 | INLIST ITERATOR | | | | | | | |
|
||||
| 186 | PARTITION RANGE ITERATOR | | 1 | 100 | 71 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 187 | INLIST ITERATOR | | | | | | | |
|
||||
| 188 | PARTITION LIST ITERATOR | | 1 | 100 | 71 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*189 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_E | 1 | 100 | 71 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*190 | INDEX RANGE SCAN | TABLE_E_UQ | 6 | | 137 (2)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 191 | PARTITION RANGE INLIST | | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 192 | PARTITION LIST SINGLE | | 1 | 100 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|*193 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_B | 1 | 100 | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
|*194 | INDEX RANGE SCAN | TABLE_D_PK | 1 | | 1 (0)| 00:00:01 | KEY(I | KEY(I |
|
||||
| 195 | PARTITION RANGE ITERATOR | | 1 | 72 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 196 | PARTITION LIST ITERATOR | | 1 | 72 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 197 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_G | 1 | 72 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|*198 | INDEX UNIQUE SCAN | TABLE_G_PK | 1 | | 0 (0)| | KEY | KEY |
|
||||
| 199 | PARTITION RANGE ITERATOR | | 1 | 38 | 0 (0)| | KEY | KEY |
|
||||
| 200 | PARTITION LIST ITERATOR | | 1 | 38 | 0 (0)| | KEY | KEY |
|
||||
|*201 | INDEX UNIQUE SCAN | TABLE_H_PK | 1 | 38 | 0 (0)| | KEY | KEY |
|
||||
| 202 | PARTITION RANGE ITERATOR | | 1 | 45 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|*203 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_I | 1 | 45 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|*204 | INDEX UNIQUE SCAN | TABLE_I_PK | 1 | | 0 (0)| | KEY | KEY |
|
||||
| 205 | PARTITION RANGE ITERATOR | | 1 | 68 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
| 206 | PARTITION LIST SINGLE | | 1 | 68 | 1 (0)| 00:00:01 | | |
|
||||
| 207 | TABLE ACCESS BY LOCAL INDEX ROWID | TABLE_F | 1 | 68 | 1 (0)| 00:00:01 | KEY | KEY |
|
||||
|*208 | INDEX UNIQUE SCAN | TABLE_F_PK | 1 | | 0 (0)| | KEY | KEY |
|
||||
| 209 | TABLE ACCESS FULL | TABLE_M | 252 | 10836 | 2 (0)| 00:00:01 | | |
|
||||
| 210 | TABLE ACCESS BY INDEX ROWID | TABLE_N | 1 | 100 | 1 (0)| 00:00:01 | | |
|
||||
|*211 | INDEX UNIQUE SCAN | TABLE_N_PK | 1 | | 0 (0)| | | |
|
||||
| 212 | TABLE ACCESS BY INDEX ROWID | TABLE_O | 1 | 58 | 1 (0)| 00:00:01 | | |
|
||||
|*213 | INDEX RANGE SCAN | TABLE_O_PK | 1 | | 0 (0)| | | |
|
||||
| 214 | TABLE ACCESS BY INDEX ROWID | TABLE_P | 1 | 58 | 1 (0)| 00:00:01 | | |
|
||||
|*215 | INDEX RANGE SCAN | TABLE_P_IDX | 1 | | 0 (0)| | | |
|
||||
| 216 | TABLE ACCESS FULL | TABLE_Q | 227 | 22019 | 2 (0)| 00:00:01 | | |
|
||||
| 217 | VIEW | | 252 | 3024 | 3 (34)| 00:00:01 | | |
|
||||
| 218 | SORT UNIQUE | | 252 | 3024 | 3 (34)| 00:00:01 | | |
|
||||
| 219 | TABLE ACCESS FULL | TABLE_M | 252 | 3024 | 2 (0)| 00:00:01 | | |
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
100
tpt/ast/index_coalesce_candidate.sql
Normal file
100
tpt/ast/index_coalesce_candidate.sql
Normal file
@@ -0,0 +1,100 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
SET LINES 1000 PAGES 5000 TRIMSPOOL ON TRIMOUT ON TAB OFF
|
||||
|
||||
COL owner FOR A15
|
||||
COL object_name FOR A30
|
||||
|
||||
WITH trends AS (
|
||||
SELECT
|
||||
o.owner
|
||||
, o.object_name
|
||||
, o.subobject_name
|
||||
, o.object_type
|
||||
, MIN(ih.savtime) first_sample
|
||||
, MAX(ih.savtime) last_sample
|
||||
, REGR_SLOPE(ih.rowcnt / NULLIF(ih.leafcnt,0), (SYSDATE-CAST(ih.savtime AS DATE)) ) regr1
|
||||
, REGR_SLOPE(ih.rowcnt, ih.leafcnt) regr2
|
||||
, ROUND(MIN(ih.rowcnt / NULLIF(ih.leafcnt,0))) min_avg_rows_per_block
|
||||
, ROUND(MAX(ih.rowcnt / NULLIF(ih.leafcnt,0))) max_avg_rows_per_block
|
||||
, MIN(ih.rowcnt) min_rowcnt
|
||||
, MAX(ih.rowcnt) max_rowcnt
|
||||
, MIN(ih.leafcnt) min_leafcnt
|
||||
, MAX(ih.leafcnt) max_leafcnt
|
||||
, MIN(ih.lblkkey) min_lblkkey
|
||||
, MAX(ih.lblkkey) max_lblkkey
|
||||
, MIN(ih.dblkkey) min_dblkkey
|
||||
, MAX(ih.dblkkey) max_dblkkey
|
||||
, MIN(ih.blevel)+1 min_height
|
||||
, MAX(ih.blevel)+1 max_height
|
||||
FROM
|
||||
dba_objects o
|
||||
, sys.wri$_optstat_ind_history ih
|
||||
WHERE
|
||||
o.object_id = ih.obj#
|
||||
AND o.object_type LIKE 'INDEX%'
|
||||
AND (
|
||||
UPPER(o.object_name) LIKE
|
||||
UPPER(CASE
|
||||
WHEN INSTR('&1','.') > 0 THEN
|
||||
SUBSTR('&1',INSTR('&1','.')+1)
|
||||
ELSE
|
||||
'&1'
|
||||
END
|
||||
)
|
||||
AND UPPER(o.owner) LIKE
|
||||
CASE WHEN INSTR('&1','.') > 0 THEN
|
||||
UPPER(SUBSTR('&1',1,INSTR('&1','.')-1))
|
||||
ELSE
|
||||
user
|
||||
END
|
||||
)
|
||||
GROUP BY
|
||||
o.owner
|
||||
, o.object_name
|
||||
, o.subobject_name
|
||||
, o.object_type
|
||||
ORDER BY
|
||||
-- ih.savtime
|
||||
regr1 DESC NULLS LAST
|
||||
)
|
||||
SELECT * FROM (
|
||||
SELECT
|
||||
t.owner
|
||||
, t.object_name
|
||||
, t.subobject_name partition_name
|
||||
, t.object_type
|
||||
, ROUND(s.bytes / 1048576) current_mb
|
||||
, CAST(first_sample AS DATE) first_sample
|
||||
, CAST(last_sample AS DATE) last_sample
|
||||
, min_avg_rows_per_block
|
||||
, max_avg_rows_per_block
|
||||
, min_leafcnt
|
||||
, max_leafcnt
|
||||
, min_lblkkey
|
||||
, max_lblkkey
|
||||
, min_dblkkey
|
||||
, max_dblkkey
|
||||
, t.regr1
|
||||
, t.regr2
|
||||
--, ROUND(SUM(s.bytes) / 1048576) mb_sum
|
||||
--, COUNT(*)
|
||||
FROM
|
||||
trends t
|
||||
, dba_segments s
|
||||
WHERE
|
||||
t.owner = s.owner
|
||||
AND t.object_name = s.segment_name
|
||||
AND t.object_type = s.segment_type
|
||||
AND (t.subobject_name = s.partition_name OR (t.subobject_name IS NULL AND s.partition_name IS NULL))
|
||||
--GROUP BY
|
||||
-- t.owner
|
||||
-- , t.object_name
|
||||
-- , t.object_type
|
||||
-- , t.subobject_name
|
||||
ORDER BY regr1 DESC NULLS LAST
|
||||
)
|
||||
WHERE
|
||||
ROWNUM<=20
|
||||
/
|
||||
26
tpt/ast/index_coalesce_candidate_detail.sql
Normal file
26
tpt/ast/index_coalesce_candidate_detail.sql
Normal file
@@ -0,0 +1,26 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
COL owner FOR A15
|
||||
COL object_name FOR A30
|
||||
|
||||
SELECT
|
||||
o.owner
|
||||
, o.object_name
|
||||
, o.object_type
|
||||
, ROUND(ih.rowcnt / NULLIF(ih.leafcnt,0)) avg_rows_per_block
|
||||
, ih.rowcnt
|
||||
, ih.leafcnt
|
||||
, ih.lblkkey
|
||||
, ih.dblkkey
|
||||
, ih.blevel
|
||||
FROM
|
||||
dba_objects o
|
||||
, sys.wri$_optstat_ind_history ih
|
||||
WHERE
|
||||
o.object_id = ih.obj#
|
||||
AND o.object_type LIKE 'INDEX%'
|
||||
AND o.object_name LIKE '&1'
|
||||
ORDER BY
|
||||
ih.savtime
|
||||
/
|
||||
9
tpt/ast/index_compress_candidate.sql
Normal file
9
tpt/ast/index_compress_candidate.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
SELECT
|
||||
i.index_name
|
||||
|
||||
|
||||
FROM
|
||||
|
||||
20
tpt/ast/index_range_scan_rereads.sql
Normal file
20
tpt/ast/index_range_scan_rereads.sql
Normal file
@@ -0,0 +1,20 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- enable physical IO tracing
|
||||
|
||||
@seg soe.orders
|
||||
@ind soe.orders
|
||||
@descxx soe.orders
|
||||
|
||||
ALTER SESSION SET EVENTS '10298 trace name context forever, level 1';
|
||||
EXEC SYS.DBMS_MONITOR.SESSION_TRACE_ENABLE(waits=>TRUE);
|
||||
|
||||
SET TIMING ON
|
||||
SET AUTOTRACE ON STAT
|
||||
|
||||
PAUSE Press enter to start...
|
||||
SELECT /*+ MONITOR INDEX(o, o(warehouse_id)) */ SUM(order_total) FROM soe.orders o WHERE warehouse_id BETWEEN 400 AND 599;
|
||||
|
||||
SET AUTOTRACE OFF
|
||||
|
||||
52
tpt/ast/new_outer_join_and_or.sql
Normal file
52
tpt/ast/new_outer_join_and_or.sql
Normal file
@@ -0,0 +1,52 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- DROP TABLE s;
|
||||
-- DROP TABLE t;
|
||||
--
|
||||
-- CREATE TABLE s AS SELECT * FROM dba_segments;
|
||||
-- CREATE TABLE t AS SELECT * FROM dba_tables;
|
||||
--
|
||||
-- SET TIMING ON
|
||||
|
||||
-- SELECT COUNT(*)
|
||||
-- FROM
|
||||
-- t
|
||||
-- , s
|
||||
-- WHERE
|
||||
-- (t.owner = s.owner AND t.table_name = s.segment_name)
|
||||
-- OR (t.owner = s.owner AND UPPER(t.table_name) = UPPER(s.segment_name))
|
||||
-- /
|
||||
--
|
||||
-- @x
|
||||
|
||||
SELECT
|
||||
/*+
|
||||
ALL_ROWS
|
||||
MERGE(@"SEL$2")
|
||||
FULL(@"SEL$64EAE176" "T"@"SEL$2")
|
||||
NO_ACCESS(@"SEL$64EAE176" "from$_subquery$_004"@"SEL$2")
|
||||
LEADING(@"SEL$64EAE176" "T"@"SEL$2" "from$_subquery$_004"@"SEL$2")
|
||||
USE_HASH(@"SEL$64EAE176" "from$_subquery$_004"@"SEL$2")
|
||||
FULL(@"SEL$1" "S"@"SEL$1")
|
||||
*/
|
||||
COUNT(*)
|
||||
FROM
|
||||
t
|
||||
LEFT OUTER JOIN
|
||||
s
|
||||
ON (
|
||||
(t.owner = s.owner AND t.table_name = s.segment_name)
|
||||
OR (t.owner = s.owner AND UPPER(t.table_name) = UPPER(s.segment_name))
|
||||
);
|
||||
|
||||
-- @x
|
||||
|
||||
-- SELECT COUNT(*) FROM (
|
||||
-- SELECT * FROM t LEFT JOIN s ON (t.owner = s.owner AND t.table_name = s.segment_name)
|
||||
-- UNION
|
||||
-- SELECT * FROM t LEFT JOIN s ON (t.owner = s.owner AND UPPER(t.table_name) = UPPER(s.segment_name))
|
||||
-- );
|
||||
--
|
||||
-- @x
|
||||
|
||||
72
tpt/ast/scalar_subquery_in_where_clause.sql
Normal file
72
tpt/ast/scalar_subquery_in_where_clause.sql
Normal file
@@ -0,0 +1,72 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- A-Times were misestimated with the default sampling
|
||||
-- ALTER SESSION SET "_rowsource_statistics_sampfreq"=1;
|
||||
ALTER SESSION SET "_serial_direct_read"=ALWAYS;
|
||||
|
||||
SELECT /*+ MONITOR test2a */
|
||||
SUM(LENGTH(object_name)) + SUM(LENGTH(object_type)) + SUM(LENGTH(owner))
|
||||
FROM
|
||||
test_objects_100m o
|
||||
WHERE
|
||||
o.owner = (SELECT u.username FROM test_users u WHERE user_id = 13)
|
||||
/
|
||||
@getprev
|
||||
@xpi &prev_sql_id
|
||||
@xia &prev_sql_id &prev_child_number
|
||||
|
||||
-- @ash/asqlmon &prev_sql_id &prev_child_number
|
||||
-- @sqlidx &prev_sql_id &prev_child_number
|
||||
|
||||
SELECT /*+ MONITOR NO_PUSH_SUBQ(@"SEL$2") test2b */
|
||||
SUM(LENGTH(object_name)) + SUM(LENGTH(object_type)) + SUM(LENGTH(owner))
|
||||
FROM
|
||||
test_objects_100m o
|
||||
WHERE
|
||||
o.owner = (SELECT u.username FROM test_users u WHERE user_id = 13)
|
||||
/
|
||||
@getprev
|
||||
-- @ash/asqlmon &prev_sql_id &prev_child_number
|
||||
-- @sqlidx &prev_sql_id &prev_child_number
|
||||
@xpi &prev_sql_id
|
||||
@xia &prev_sql_id &prev_child_number
|
||||
|
||||
-- ALTER SESSION SET "_rowsource_statistics_sampfreq"=128;
|
||||
|
||||
|
||||
SELECT /*+ MONITOR OPT_PARAM('cell_offload_processing', 'false') test3a */
|
||||
SUM(LENGTH(object_name)) + SUM(LENGTH(object_type)) + SUM(LENGTH(owner))
|
||||
FROM
|
||||
test_objects_100m o
|
||||
WHERE
|
||||
o.owner = (SELECT u.username FROM test_users u WHERE user_id = 13)
|
||||
/
|
||||
|
||||
SELECT /*+ MONITOR NO_PUSH_SUBQ(@"SEL$2") OPT_PARAM('cell_offload_processing', 'false') test3b */
|
||||
SUM(LENGTH(object_name)) + SUM(LENGTH(object_type)) + SUM(LENGTH(owner))
|
||||
FROM
|
||||
test_objects_100m o
|
||||
WHERE
|
||||
o.owner = (SELECT u.username FROM test_users u WHERE user_id = 13)
|
||||
/
|
||||
|
||||
|
||||
SELECT /*+ MONITOR PUSH_SUBQ(@"SEL$2") OPT_PARAM('cell_offload_processing', 'true') test4a */
|
||||
SUM(LENGTH(object_name)) + SUM(LENGTH(object_type)) + SUM(LENGTH(owner))
|
||||
FROM
|
||||
test_objects_100m o
|
||||
WHERE
|
||||
o.owner = (SELECT u.username FROM test_users u WHERE user_id = 13)
|
||||
/
|
||||
|
||||
SELECT /*+ MONITOR NO_PUSH_SUBQ(@"SEL$2") OPT_PARAM('cell_offload_processing', 'true') test4b */
|
||||
SUM(LENGTH(object_name)) + SUM(LENGTH(object_type)) + SUM(LENGTH(owner))
|
||||
FROM
|
||||
test_objects_100m o
|
||||
WHERE
|
||||
o.owner = (SELECT u.username FROM test_users u WHERE user_id = 13)
|
||||
/
|
||||
|
||||
|
||||
|
||||
39
tpt/ast/scalar_subquery_unnesting.sql
Normal file
39
tpt/ast/scalar_subquery_unnesting.sql
Normal file
@@ -0,0 +1,39 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- DROP TABLE test_users;
|
||||
-- DROP TABLE test_objects;
|
||||
CREATE TABLE test_users AS SELECT * FROM all_users;
|
||||
CREATE TABLE test_objects AS SELECT * FROM all_objects;
|
||||
@gts test_users
|
||||
@gts test_objects
|
||||
|
||||
@53on
|
||||
|
||||
SELECT /*+ GATHER_PLAN_STATISTICS */
|
||||
u.username
|
||||
, (SELECT MAX(created) FROM test_objects o WHERE o.owner = u.username)
|
||||
FROM
|
||||
test_users u
|
||||
WHERE
|
||||
username LIKE 'S%'
|
||||
/
|
||||
|
||||
@53off
|
||||
@xall
|
||||
@53on
|
||||
|
||||
-- ALTER SESSION SET "_optimizer_unnest_scalar_sq" = FALSE;
|
||||
|
||||
SELECT /*+ GATHER_PLAN_STATISTICS NO_UNNEST(@ssq) */
|
||||
u.username
|
||||
, (SELECT /*+ QB_NAME(ssq) */ MAX(created) FROM test_objects o WHERE o.owner = u.username)
|
||||
FROM
|
||||
test_users u
|
||||
WHERE
|
||||
username LIKE 'S%'
|
||||
/
|
||||
|
||||
@53off
|
||||
@xall
|
||||
|
||||
55
tpt/ast/soe_query.sql
Normal file
55
tpt/ast/soe_query.sql
Normal file
@@ -0,0 +1,55 @@
|
||||
------------------------------------------------------------------------------
|
||||
--
|
||||
-- Copyright 2017 Tanel Poder ( tanel@tanelpoder.com | http://tanelpoder.com )
|
||||
--
|
||||
-- Licensed under the Apache License, Version 2.0 (the "License");
|
||||
-- you may not use this file except in compliance with the License.
|
||||
-- You may obtain a copy of the License at
|
||||
--
|
||||
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||
--
|
||||
-- Unless required by applicable law or agreed to in writing, software
|
||||
-- distributed under the License is distributed on an "AS IS" BASIS,
|
||||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
-- See the License for the specific language governing permissions and
|
||||
-- limitations under the License.
|
||||
--
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
ALTER SESSION SET plsql_optimize_level = 0;
|
||||
|
||||
DECLARE
|
||||
n NUMBER;
|
||||
BEGIN
|
||||
FOR i IN 1 .. &1 LOOP
|
||||
n := DBMS_RANDOM.VALUE;
|
||||
EXECUTE IMMEDIATE q'[SELECT
|
||||
prod.product_name
|
||||
, c.cust_first_name
|
||||
, c.cust_last_name
|
||||
, SUM(oi.quantity)
|
||||
, sum(oi.unit_price * oi.quantity) total_price
|
||||
FROM
|
||||
soe.orders o
|
||||
, soe.order_items oi
|
||||
, soe.products prod
|
||||
, soe.customers c
|
||||
WHERE
|
||||
-- joins
|
||||
o.order_id = oi.order_id
|
||||
AND oi.product_id = prod.product_id
|
||||
AND o.customer_id = c.customer_id
|
||||
-- filters
|
||||
AND prod.product_name = 'Mobile Web Phone'||:v
|
||||
AND LOWER(c.cust_first_name) = LOWER('Gena'||:v)
|
||||
AND LOWER(c.cust_last_name) = LOWER('Harris'||:v)
|
||||
GROUP BY
|
||||
prod.product_name
|
||||
, c.cust_first_name
|
||||
, c.cust_last_name
|
||||
ORDER BY
|
||||
total_price]'
|
||||
USING n, n, n;
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
/
|
||||
25
tpt/ast/subquery_execution.sql
Normal file
25
tpt/ast/subquery_execution.sql
Normal file
@@ -0,0 +1,25 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
-- starting from 10g, the push_subq hint must be specified in the subquery block
|
||||
-- you wish to push earlier (or with the @subq hint addressing)
|
||||
|
||||
select
|
||||
e.*
|
||||
, d.dname
|
||||
from
|
||||
scott.emp e
|
||||
, scott.dept d
|
||||
where
|
||||
e.deptno = d.deptno
|
||||
and exists (
|
||||
select /*+ no_unnest push_subq */
|
||||
1
|
||||
from
|
||||
scott.bonus b
|
||||
where
|
||||
b.ename = e.ename
|
||||
and b.job = e.job
|
||||
)
|
||||
/
|
||||
|
||||
32
tpt/ast/test_index_coalesce_candidate.sql
Normal file
32
tpt/ast/test_index_coalesce_candidate.sql
Normal file
@@ -0,0 +1,32 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
DROP TABLE tcoal;
|
||||
DROP SEQUENCE scoal;
|
||||
CREATE TABLE tcoal (id NUMBER, a VARCHAR2(100), b VARCHAR2(100)) TABLESPACE users;
|
||||
CREATE INDEX icoal1 ON tcoal(id) TABLESPACE users;
|
||||
CREATE INDEX icoal2 ON tcoal(id,a) TABLESPACE users;
|
||||
CREATE INDEX icoal3 ON tcoal(b) TABLESPACE users;
|
||||
CREATE SEQUENCE scoal CACHE 10000;
|
||||
|
||||
BEGIN FOR i IN 1..100 LOOP
|
||||
INSERT INTO tcoal SELECT scoal.NEXTVAL, DBMS_RANDOM.STRING('a', 20), DBMS_RANDOM.STRING('a', 20)
|
||||
FROM dual CONNECT BY LEVEL <= 10000;
|
||||
COMMIT;
|
||||
DBMS_STATS.GATHER_INDEX_STATS(user, 'ICOAL1');
|
||||
DBMS_STATS.GATHER_INDEX_STATS(user, 'ICOAL2');
|
||||
DBMS_STATS.GATHER_INDEX_STATS(user, 'ICOAL3');
|
||||
END LOOP; END;
|
||||
/
|
||||
|
||||
BEGIN FOR i in 1..100 LOOP
|
||||
DELETE FROM tcoal WHERE MOD(id,100)!=0 AND rownum <= 10000;
|
||||
INSERT INTO tcoal SELECT scoal.NEXTVAL, DBMS_RANDOM.STRING('a', 20), DBMS_RANDOM.STRING('a', 20)
|
||||
FROM dual CONNECT BY LEVEL <= 10000;
|
||||
|
||||
DBMS_STATS.GATHER_INDEX_STATS(user, 'ICOAL1');
|
||||
DBMS_STATS.GATHER_INDEX_STATS(user, 'ICOAL2');
|
||||
DBMS_STATS.GATHER_INDEX_STATS(user, 'ICOAL3');
|
||||
END LOOP; END;
|
||||
/
|
||||
|
||||
116
tpt/ast/test_plan.txt
Normal file
116
tpt/ast/test_plan.txt
Normal file
@@ -0,0 +1,116 @@
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | Writes | OMem | 1Mem | Used-Mem |
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
| 0 | SELECT STATEMENT | | 1 | | 2 |00:00:06.65 | 50499 | 2086 | 1041 | | | |
|
||||
| 1 | TEMP TABLE TRANSFORMATION | | 1 | | 2 |00:00:06.65 | 50499 | 2086 | 1041 | | | |
|
||||
| 2 | LOAD AS SELECT | | 1 | | 0 |00:00:06.32 | 48405 | 2 | 1041 | 530K| 530K| 530K (0)|
|
||||
|* 3 | TABLE ACCESS BY INDEX ROWID | SUM$ | 3 | 1 | 0 |00:00:00.01 | 3 | 0 | 0 | | | |
|
||||
|* 4 | INDEX UNIQUE SCAN | I_SUM$_1 | 3 | 1 | 3 |00:00:00.01 | 2 | 0 | 0 | | | |
|
||||
| 5 | TABLE ACCESS BY INDEX ROWID | OBJ$ | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 6 | INDEX RANGE SCAN | I_OBJ1 | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 7 | FILTER | | 1 | | 73027 |00:00:05.77 | 47342 | 2 | 0 | | | |
|
||||
|* 8 | HASH JOIN | | 1 | 74860 | 74936 |00:00:00.79 | 948 | 0 | 0 | 1063K| 1063K| 1234K (0)|
|
||||
| 9 | TABLE ACCESS FULL | USER$ | 1 | 104 | 104 |00:00:00.01 | 7 | 0 | 0 | | | |
|
||||
|* 10 | HASH JOIN | | 1 | 74860 | 74936 |00:00:00.51 | 941 | 0 | 0 | 981K| 981K| 1254K (0)|
|
||||
| 11 | INDEX FULL SCAN | I_USER2 | 1 | 104 | 104 |00:00:00.01 | 1 | 0 | 0 | | | |
|
||||
|* 12 | TABLE ACCESS FULL | OBJ$ | 1 | 74860 | 74936 |00:00:00.18 | 940 | 0 | 0 | | | |
|
||||
|* 13 | TABLE ACCESS BY INDEX ROWID | IND$ | 4995 | 1 | 4087 |00:00:00.04 | 933 | 0 | 0 | | | |
|
||||
|* 14 | INDEX UNIQUE SCAN | I_IND1 | 4995 | 1 | 4995 |00:00:00.01 | 134 | 0 | 0 | | | |
|
||||
|* 15 | HASH JOIN | | 25955 | 1 | 24502 |00:00:03.60 | 26661 | 0 | 0 | 981K| 981K| 1051K (0)|
|
||||
|* 16 | INDEX RANGE SCAN | I_OBJAUTH1 | 25955 | 1 | 24747 |00:00:00.19 | 26661 | 0 | 0 | | | |
|
||||
| 17 | FIXED TABLE FULL | X$KZSRO | 24589 | 100 | 27424 |00:00:00.18 | 0 | 0 | 0 | | | |
|
||||
|* 18 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 19 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 20 | NESTED LOOPS | | 1645 | 1 | 96 |00:00:00.01 | 1865 | 0 | 0 | | | |
|
||||
|* 21 | INDEX RANGE SCAN | I_OBJAUTH1 | 1645 | 1 | 133 |00:00:00.01 | 1865 | 0 | 0 | | | |
|
||||
|* 22 | FIXED TABLE FULL | X$KZSRO | 133 | 1 | 96 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 23 | HASH JOIN | | 2845 | 1 | 1478 |00:00:00.48 | 3051 | 0 | 0 | 990K| 990K| 485K (0)|
|
||||
|* 24 | INDEX RANGE SCAN | I_OBJAUTH1 | 2845 | 1 | 1551 |00:00:00.02 | 3051 | 0 | 0 | | | |
|
||||
| 25 | FIXED TABLE FULL | X$KZSRO | 1493 | 100 | 1853 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 26 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 27 | NESTED LOOPS | | 1255 | | 0 |00:00:00.35 | 7429 | 0 | 0 | | | |
|
||||
| 28 | NESTED LOOPS | | 1255 | 1 | 0 |00:00:00.35 | 7429 | 0 | 0 | | | |
|
||||
| 29 | NESTED LOOPS | | 1255 | 1 | 0 |00:00:00.35 | 7429 | 0 | 0 | | | |
|
||||
| 30 | NESTED LOOPS | | 1255 | 1 | 28865 |00:00:00.25 | 4702 | 0 | 0 | | | |
|
||||
| 31 | MERGE JOIN CARTESIAN | | 1255 | 1 | 28865 |00:00:00.12 | 3445 | 0 | 0 | | | |
|
||||
|* 32 | INDEX RANGE SCAN | I_OBJ5 | 1255 | 1 | 1255 |00:00:00.01 | 3445 | 0 | 0 | | | |
|
||||
| 33 | BUFFER SORT | | 1255 | 100 | 28865 |00:00:00.07 | 0 | 0 | 0 | 2048 | 2048 | 2048 (0)|
|
||||
| 34 | FIXED TABLE FULL | X$KZSRO | 1255 | 100 | 28865 |00:00:00.03 | 0 | 0 | 0 | | | |
|
||||
|* 35 | INDEX RANGE SCAN | I_USER2 | 28865 | 1 | 28865 |00:00:00.07 | 1257 | 0 | 0 | | | |
|
||||
|* 36 | INDEX RANGE SCAN | I_OBJAUTH1 | 28865 | 1 | 0 |00:00:00.06 | 2727 | 0 | 0 | | | |
|
||||
|* 37 | INDEX RANGE SCAN | I_DEPENDENCY1 | 0 | 3 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 38 | TABLE ACCESS BY INDEX ROWID | DEPENDENCY$ | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 39 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 40 | NESTED LOOPS | | 617 | 1 | 7 |00:00:00.01 | 1923 | 0 | 0 | | | |
|
||||
| 41 | NESTED LOOPS | | 617 | 1 | 19 |00:00:00.01 | 1923 | 0 | 0 | | | |
|
||||
|* 42 | TABLE ACCESS BY INDEX ROWID | TRIGGER$ | 617 | 1 | 592 |00:00:00.01 | 1245 | 0 | 0 | | | |
|
||||
|* 43 | INDEX UNIQUE SCAN | I_TRIGGER2 | 617 | 1 | 617 |00:00:00.01 | 628 | 0 | 0 | | | |
|
||||
|* 44 | INDEX RANGE SCAN | I_OBJAUTH1 | 592 | 1 | 19 |00:00:00.01 | 678 | 0 | 0 | | | |
|
||||
|* 45 | FIXED TABLE FULL | X$KZSRO | 19 | 1 | 7 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 46 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 47 | NESTED LOOPS | | 240 | | 0 |00:00:00.07 | 1471 | 0 | 0 | | | |
|
||||
| 48 | NESTED LOOPS | | 240 | 1 | 0 |00:00:00.07 | 1471 | 0 | 0 | | | |
|
||||
| 49 | NESTED LOOPS | | 240 | 1 | 0 |00:00:00.07 | 1471 | 0 | 0 | | | |
|
||||
| 50 | NESTED LOOPS | | 240 | 1 | 5727 |00:00:00.05 | 926 | 0 | 0 | | | |
|
||||
| 51 | MERGE JOIN CARTESIAN | | 240 | 1 | 5727 |00:00:00.02 | 684 | 0 | 0 | | | |
|
||||
|* 52 | INDEX RANGE SCAN | I_OBJ5 | 240 | 1 | 249 |00:00:00.01 | 684 | 0 | 0 | | | |
|
||||
| 53 | BUFFER SORT | | 249 | 100 | 5727 |00:00:00.01 | 0 | 0 | 0 | 2048 | 2048 | 2048 (0)|
|
||||
| 54 | FIXED TABLE FULL | X$KZSRO | 240 | 100 | 5520 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 55 | INDEX RANGE SCAN | I_USER2 | 5727 | 1 | 5727 |00:00:00.01 | 242 | 0 | 0 | | | |
|
||||
|* 56 | INDEX RANGE SCAN | I_OBJAUTH1 | 5727 | 1 | 0 |00:00:00.01 | 545 | 0 | 0 | | | |
|
||||
|* 57 | INDEX RANGE SCAN | I_DEPENDENCY1 | 0 | 3 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 58 | TABLE ACCESS BY INDEX ROWID | DEPENDENCY$ | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 59 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 60 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 61 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 62 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 63 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 64 | FIXED TABLE FULL | X$KZSPR | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 65 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 66 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 67 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 68 | VIEW | | 52 | 1 | 52 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 69 | FAST DUAL | | 52 | 1 | 52 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 70 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 71 | FIXED TABLE FULL | X$KZSPR | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 72 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 73 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 74 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 75 | FIXED TABLE FULL | X$KZSPR | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 76 | FIXED TABLE FULL | X$KZSPR | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 77 | FIXED TABLE FULL | X$KZSPR | 1 | 1 | 1 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 78 | FIXED TABLE FULL | X$KZSPR | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 79 | FIXED TABLE FULL | X$KZSPR | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 80 | FIXED TABLE FULL | X$KZSPR | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 81 | FIXED TABLE FULL | X$KZSPR | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 82 | NESTED LOOPS | | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 83 | INDEX RANGE SCAN | I_OBJAUTH1 | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 84 | FIXED TABLE FULL | X$KZSRO | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 85 | FIXED TABLE FULL | X$KZSPR | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 86 | NESTED LOOPS | | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 87 | INDEX RANGE SCAN | I_OBJAUTH1 | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 88 | FIXED TABLE FULL | X$KZSRO | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 89 | FIXED TABLE FULL | X$KZSPR | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 90 | VIEW | | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 91 | SORT GROUP BY | | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | 73728 | 73728 | |
|
||||
| 92 | NESTED LOOPS | | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 93 | MERGE JOIN CARTESIAN | | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 94 | NESTED LOOPS | | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 95 | INDEX UNIQUE SCAN | I_OLAP_CUBES$ | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 96 | TABLE ACCESS BY INDEX ROWID| OLAP_DIMENSIONALITY$ | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|* 97 | INDEX RANGE SCAN | I_OLAP_DIMENSIONALITY$ | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 98 | BUFFER SORT | | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | 73728 | 73728 | |
|
||||
| 99 | INDEX FULL SCAN | I_OLAP_CUBE_DIMENSIONS$ | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|*100 | INDEX RANGE SCAN | I_OBJ1 | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 101 | NESTED LOOPS | | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|*102 | INDEX FULL SCAN | I_USER2 | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
|*103 | INDEX RANGE SCAN | I_OBJ4 | 0 | 1 | 0 |00:00:00.01 | 0 | 0 | 0 | | | |
|
||||
| 104 | UNION-ALL | | 1 | | 2 |00:00:00.33 | 2091 | 2084 | 0 | | | |
|
||||
| 105 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.18 | 1047 | 1042 | 0 | | | |
|
||||
| 106 | VIEW | | 1 | 31935 | 73027 |00:00:00.13 | 1047 | 1042 | 0 | | | |
|
||||
| 107 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6637_489CA79 | 1 | 31935 | 73027 |00:00:00.07 | 1047 | 1042 | 0 | | | |
|
||||
| 108 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.15 | 1044 | 1042 | 0 | | | |
|
||||
| 109 | VIEW | | 1 | 31935 | 73027 |00:00:00.12 | 1044 | 1042 | 0 | | | |
|
||||
| 110 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6637_489CA79 | 1 | 31935 | 73027 |00:00:00.05 | 1044 | 1042 | 0 | | | |
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
10950
tpt/ast/trace/04_cbo_troubleshoot_1.trc
Normal file
10950
tpt/ast/trace/04_cbo_troubleshoot_1.trc
Normal file
File diff suppressed because it is too large
Load Diff
10920
tpt/ast/trace/a.txt
Normal file
10920
tpt/ast/trace/a.txt
Normal file
File diff suppressed because it is too large
Load Diff
13
tpt/ast/trace/cbo_analyze.sh
Normal file
13
tpt/ast/trace/cbo_analyze.sh
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
cat $1 | awk '
|
||||
|
||||
function p(str) { printf("%6d: %s\n", NR, str) ; return 0 }
|
||||
|
||||
/Now joining|Join order/{ p($0) }
|
||||
|
||||
/^Best::/{ x=1 ; p($0) }
|
||||
|
||||
(!/Best::/ && x ==1) { p($0) ; x=0 }
|
||||
|
||||
'
|
||||
16
tpt/ast/use_concat.sql
Normal file
16
tpt/ast/use_concat.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
DROP TABLE t;
|
||||
|
||||
CREATE TABLE t AS SELECT * FROM dba_objects;
|
||||
|
||||
CREATE INDEX t_i1 ON t (object_id);
|
||||
CREATE INDEX t_i2 ON t (data_object_id);
|
||||
|
||||
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T');
|
||||
|
||||
SELECT owner FROM t WHERE object_id = 123 OR data_object_id = 456;
|
||||
|
||||
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null,null,'+OUTLINE'));
|
||||
|
||||
Reference in New Issue
Block a user