Flashback Snapshot of Schema

Few days ago, one of my clients performed a "drop" action occidentally on the web
site. But he could not confirm what he dropped is correct or not. He want to see the
screen before he dropped the items.
The first thought we got is to utilize flashback query. However, this simple action
actually deleted important data from many tables (over 10), and the code of displaying
the i is fairly complex. Flashback query doesn't help in this case. We finally exported
entire schema using expdp with flashback_time option, and imported it to a test
environment.
I ever thought if oracle provided a session parameter flashback_scn/flashback_time to
allow the user flashback query all of data to a specified scn/timestamp in the session,
it will make things simple. What we need to do is to create a new connection, and
change this parameter after connected to database.
Then I was thinking can I find a workaround way? I finally got one. I can build a new
schema, then create a set of views referring to the existing schema, involving the
flashback query feature. And I can use a "global parameter" to control the flashback
scn/timestamp.
Here is the code.
SQL 代码
1. -- ############################################################################
####
2. -- #
3. -- #

$Id: schema_snapshot.sql

4. -- #
5. -- #

File: $RCSfile: schema_snapshot.sql,v $

6. -- # Description: create a snapshot for a schema
7. -- #
Usage: sqlplus -s /nolog @schema_snapshot <existing_schema_name> <sn
apshot_schema_name>
8. -- #

Created: 07/02/2014

9. -- #

Author: Wei Huang

10. -- # User run as: / as sysdba (OS user should be oracle owner)
11. -- #

Parameters: 1: existing schema name

12. -- #

Parameters: 2: new schema name

13. -- #

Parameters: 3: snapshot timestamp

14. -- #
15. -- #

Copyright (c) 2014 Wei Huang

16. -- #
17. -- # History
18. -- # Modified by

When

Why

19. -- # ------------

-------

--------------------------------------------------

20. -- ############################################################################
####
21.
22. prompt Usage: @schema_snapshot <existing_schema_name> <snapshot_schema_name>
23. prompt Description: create a snapshot for a schema
24. prompt
25.
26. declare
27.

sql_str varchar2(4000);

28.

c number;

29. begin
30.

select count(1) into c from dba_users where username = upper('&2');

31.

if c = 0 then

32.

execute immediate 'create user &2 identified by &2';

33.

execute immediate 'grant connect,resource to &2';

34.

sql_str := q'[

35. CREATE OR REPLACE PACKAGE &2.var_pkg IS
36.

var varchar2(255);

37.

PROCEDURE set_var(val varchar2);

38.

function get_var return varchar2;

39. END var_pkg ;
40. /
41.
42. CREATE OR REPLACE PACKAGE BODY &2.var_pkg IS
43.

PROCEDURE set_var(val varchar2) IS

44.

BEGIN

45.

var := val;

46.

end set_var;

47.
48.

function get_var return varchar2

49.

IS

50.

BEGIN

51.

return var;

52.

END get_var;

53. END var_pkg;
54. /
55. ]';
56.
57.
58.

59.
60.

execute immediate sql_str;
for q in (select 'grant select,flashback on '||owner||'.'||table_name||' to
'||upper('&2')||';' str from dba_tables where owner=upper('&1')) loop
execute immediate q.str;
end loop;

61.

for q in (select 'create or replace view '||upper('&2')||'.V_'||
table_name||' as select * from '||owner||'.'||table_name||' as of timestamp to
_timestamp(var_pkg.get_var,''yyyymmddhh24miss'');' from dba_tables where owner=
upper('&1') loop

62.

execute immediate q.str;

63.
64.

end loop;
for q in (select 'create or replace synonym '||upper('&2')||'.'||
table_name||' for '||upper('&2')||'.V_'||table_name||';' from dba_tables where
owner=upper('&1') loop

65.

execute immediate q.str;

66.

end loop;

67.
68.
69.

&2.var_pkg.set_var('&3');
end if;

70. end;
71. /

This will generate the code to create a "snapshot schema". Clients connecting this
schema will query all the data before the specified time. Of course, if there are
procedures/views in the existing schema, they should be created in the new schema
referring to those synonyms.

Consistent Gets may not tell the truth
Consistent gets is important statistics data indicating the performance of a SQL. It's a
metric data for us to tune SQL. Normally, we may compare the performance of two
SQL or same SQL with different execution plan. However, sometimes, CG may not
tell us the release performance of SQL.
Let's review below 2 statistics data output first.
SQL 代码
1. SQL 1:
2. Statistics

3. ---------------------------------------------------------4.

0

recursive calls

5.

0

db block gets

6.

460

7.

0

physical reads

8.

0

redo size

9.

1203583

consistent gets

bytes sent via SQL*Net to client

10.

3868

bytes received via SQL*Net from client

11.

306

12.

0

sorts (memory)

13.

0

sorts (disk)

14.

4563

SQL*Net roundtrips to/from client

rows processed

15.
16. SQL 2:
17. Statistics
18. ---------------------------------------------------------19.

0

recursive calls

20.

0

db block gets

21.

167

22.

0

physical reads

23.

0

redo size

24.

267325

25.

3868

26.

306

27.

1

sorts (memory)

28.

0

sorts (disk)

29.

4563

consistent gets

bytes sent via SQL*Net to client
bytes received via SQL*Net from client
SQL*Net roundtrips to/from client

rows processed

The consistent gets of the 1st SQL is almost 3 times of the 2nd one. Seems the 2nd
must have better performance. Isn't it?
Ok, let's go back to see how did these data got.
SQL 代码
1. HelloDBA.COM> create table t1 as select * from dba_tables;
2.
3. Table created.
4.
5. HelloDBA.COM> create table t2 as select * from dba_users;
6.
7. Table created.
8.
9. HelloDBA.COM> exec dbms_stats.gather_table_stats('DEMO', 'T1');
10.
11. PL/SQL procedure successfully completed.
12.
13. HelloDBA.COM> exec dbms_stats.gather_table_stats('DEMO', 'T2');
14.
15. PL/SQL procedure successfully completed.
16.
17. HelloDBA.COM> set timing on
18. HelloDBA.COM> set autot trace
19. HelloDBA.COM> select * from t1;
20.
21. 4563 rows selected.
22.
23. Elapsed: 00:00:00.10

24.
25. Execution Plan
26. ---------------------------------------------------------27. Plan hash value: 3617692013
28.
29. -------------------------------------------------------------------------30. | Id

| Operation

| Name | Rows

| Bytes | Cost (%CPU)| Time

|

31. -------------------------------------------------------------------------32. |

0 | SELECT STATEMENT

33. |

1 |

|

TABLE ACCESS FULL| T1

|

4563 |

1078K|

49

(0)| 00:00:01 |

|

4563 |

1078K|

49

(0)| 00:00:01 |

34. -------------------------------------------------------------------------35.
36.
37. Statistics
38. ---------------------------------------------------------39.

0

recursive calls

40.

0

db block gets

41.

460

42.

0

physical reads

43.

0

redo size

44.

1203583

45.

3868

46.

306

47.

0

sorts (memory)

48.

0

sorts (disk)

49.

4563

50.

consistent gets

bytes sent via SQL*Net to client
bytes received via SQL*Net from client
SQL*Net roundtrips to/from client

rows processed

51. HelloDBA.COM> select * from t1, t2 where t2.username='SYS';
52.
53. 4563 rows selected.
54.
55. Elapsed: 00:00:00.23
56.
57. Execution Plan
58. ---------------------------------------------------------59. Plan hash value: 1323614827
60.
61. ----------------------------------------------------------------------------62. | Id

| Operation

| Name | Rows

| Bytes | Cost (%CPU)| Time

|

63. ----------------------------------------------------------------------------64. |

0 | SELECT STATEMENT

|

|

4563 |

1581K|

52

(0)| 00:00:01 |

65. |

1 |

MERGE JOIN CARTESIAN|

|

4563 |

1581K|

52

(0)| 00:00:01 |

66. |*

2 |

TABLE ACCESS FULL

| T2

|

1 |

113 |

3

(0)| 00:00:01 |

67. |

3 |

BUFFER SORT

|

|

4563 |

1078K|

49

(0)| 00:00:01 |

68. |

4 |

|

4563 |

1078K|

49

(0)| 00:00:01 |

TABLE ACCESS FULL | T1

69. ----------------------------------------------------------------------------70.
71. Predicate Information (identified by operation id):
72. --------------------------------------------------73.
74.

2 - filter("T2"."USERNAME"='SYS')

75.
76.
77. Statistics

78. ---------------------------------------------------------79.

0

recursive calls

80.

0

db block gets

81.

167

82.

0

physical reads

83.

0

redo size

84.

267325

85.

3868

86.

306

87.

1

sorts (memory)

88.

0

sorts (disk)

89.

4563

consistent gets

bytes sent via SQL*Net to client
bytes received via SQL*Net from client
SQL*Net roundtrips to/from client

rows processed

These 2 SQLs are simple. If we ignore the performance statistics data, we can easily
determine their performance from their logical structure or from their execution plan
--- The performance of the 1st one must be better than the 2nd one, because there is
one more full table scan in the execution plan.
Then why the 2nd one has less consistent gets?
Set SQL Trace for them, and then look into the formatted trace file.
SQL 代码
1. Rows (1st) Rows (avg) Rows (max)

Row Source Operation

2. ---------- ---------- ---------------

---------------------------------------------

3.

4563
4563
4563 MERGE JOIN CARTESIAN (cr=167 pr=0 pw=0 time=3
8433 us cost=52 size=1619865 card=4563)

4.

1
1
us cost=3 size=113 card=1)

5.

4563
4563
4563
cost=49 size=1104246 card=4563)

6.

4563
4563
4563
TABLE ACCESS FULL T1 (cr=164 pr=0 pw=0 time
=11815 us cost=49 size=1104246 card=4563)

1

TABLE ACCESS FULL T2 (cr=3 pr=0 pw=0 time=78

BUFFER SORT (cr=164 pr=0 pw=0 time=22958 us

This is the plan statistics data of the 2nd SQL. Obviously, there are 2 parts of
consistent gets, FTS on t1 and FTS on t2.
In this plan, FTS on t1 is 164. But why the 1st SQL got 466? That is because of fetch
array size. Default array size of SQL*Plus is 15. If we set it large enough, it will be,
SQL 代码
1. HelloDBA.COM> set arraysize 5000
2. HelloDBA.COM> set autot trace stat
3. HelloDBA.COM> select * from t1;
4.
5. Statistics
6. ---------------------------------------------------------7.

0

recursive calls

8.

0

db block gets

9.

165

consistent gets

10.

0

physical reads

11.

0

redo size

12.

1147039

13.

524

14.

2

SQL*Net roundtrips to/from client

15.

0

sorts (memory)

16.

0

sorts (disk)

17.

4563

bytes sent via SQL*Net to client
bytes received via SQL*Net from client

rows processed

165. Yes, becasue no matter how large of the array size, oracle will always retrieve the
1st row in the 1st fetch. More details refer to this article.
http://www.hellodba.com/reader.php?ID=39&lang=EN
F2 is a fairly small, consistent gets is just 3, it makes sense.
Is this the end of the story? No, let remove the filter from the 2nd SQL,

SQL 代码
1. HelloDBA.COM> select * from t1, t2;
2.
3. 246402 rows selected.
4.
5.
6. Statistics
7. ---------------------------------------------------------8.

1

recursive calls

9.

0

db block gets

10.

219

consistent gets

11.

0

physical reads

12.

0

redo size

13.

14113903

14.

181209

15.

16428

16.

1

sorts (memory)

17.

0

sorts (disk)

18.

246402

bytes sent via SQL*Net to client
bytes received via SQL*Net from client
SQL*Net roundtrips to/from client

rows processed

Only 219 consistent gets? It's a Cartesian Join, how come the small consistent gets is
it?
Generate the SQL trace file again,
SQL 代码
1. Rows (1st) Rows (avg) Rows (max)

Row Source Operation

2. ---------- ---------- ---------------

---------------------------------------------

3.

246402
246402
246402 MERGE JOIN CARTESIAN (cr=219 pr=0 pw=0 time=9
57833 us cost=2553 size=87472710 card=246402)

4.

54
54
54
28 us cost=3 size=6102 card=54)

TABLE ACCESS FULL T2 (cr=55 pr=0 pw=0 time=7

5.

246402
246402
246402
cost=2550 size=1104246 card=4563)

BUFFER SORT (cr=164 pr=0 pw=0 time=433549 us

6.

4563
4563
4563
TABLE ACCESS FULL T1 (cr=164 pr=0 pw=0 time
=10674 us cost=47 size=1104246 card=4563)

CR of FTS on t1 is unchanged, while CR of FTS on t2 is increased to 55.
What is this number? It's row number of T2 plus 1.
SQL 代码
1. HelloDBA.COM> select count(*) from t2;
2.
3.

COUNT(*)

4. ---------5.

54

But wait, logically, Cartesian Join means n*m, right? How come a result of n+m?
Actually, Oracle do read the data of t1 for multiple times (54). However, after first
scan on t1, data has been cached into private work area, the following reads are from
the private buffer instead of shared buffer. Therefore, they are not counted into
consistent gets.
To get its real "gets", we may use nested loop join hint to force it read data from
shared buffer instead of private buffer.
SQL 代码
1. HelloDBA.COM> select /*+use_nl(t1) leading(t1)*/* from t1, t2;
2.
3. 246402 rows selected.
4.
5. Elapsed: 00:00:07.43
6.
7. Execution Plan

8. ---------------------------------------------------------9. Plan hash value: 787647388
10.
11. ----------------------------------------------------------------------------12. | Id

| Operation

| Name | Rows

| Bytes | Cost (%CPU)| Time

|

13. ----------------------------------------------------------------------------14. |

0 | SELECT STATEMENT

|

|

246K|

83M|

5006

(1)| 00:01:01 |

15. |

1 |

MERGE JOIN CARTESIAN|

|

246K|

83M|

5006

(1)| 00:01:01 |

16. |

2 |

TABLE ACCESS FULL

| T1

|

4563 |

1078K|

49

(0)| 00:00:01 |

17. |

3 |

BUFFER SORT

|

|

54 |

6102 |

4956

(1)| 00:01:00 |

18. |

4 |

|

54 |

6102 |

1

(0)| 00:00:01 |

TABLE ACCESS FULL | T2

19. ----------------------------------------------------------------------------20.
21.
22. Statistics
23. ---------------------------------------------------------24.

0

recursive calls

25.

0

db block gets

26.

4568

27.

0

physical reads

28.

0

redo size

29.

16632868

30.

181209

31.

16428

32.

1

sorts (memory)

33.

0

sorts (disk)

34.

246402

consistent gets

bytes sent via SQL*Net to client
bytes received via SQL*Net from client
SQL*Net roundtrips to/from client

rows processed

Although the execution plan is not changed, the consistents gets is increased
significantly.

What we should note from this case is,
Fetch array size affects the consistent gets.
Consistent gets statistics data will only include the gets from shared buffer;

Test environment: Oracle 11.2.0.3 on Oracle Linux 5 64bit

One single SQL helps you to analyze the
performance of a SQL
This is the script I am using to analyze SQL performance. It major contains one SQL
only. It can show below information if available. And you can shoose to show parts of
them.

* Monitored/Captured Bind Variables

* SQL Text

* Execution Plan

* PeeKed Binds of the execution plan

* Plan Outline Data

* Plan Predicate

* Plan Lines Loading

* Wait events

* Performance Statistics Data

Example:
SQL 代码
1. HelloDBA.COM> @showplan 8z91j441gu9n1
2. Usage: @showplan <SQL_ID> [Plan Hash Value] [Details: [+](B)inds|SQL (T)ext|
(Pee(K)ed Binds|(P)lan|(O)utlines|Pre(D)icate|Plan (L)oading|(W)ait events|
(S)tatistics]
3. Description: Show SQL Plan
4.
5.
6. SQL ID: 8z91j441gu9n1
7.
8. ------------- Last Monitored Binds -------------9.
10. --SID: 258,16699
11. var ACCEPTDIS VARCHAR2(32)
12. var BENAME VARCHAR2(32)
13. var EENAME VARCHAR2(32)
14. var IMPLTYP VARCHAR2(32)
15. var PROFILETYP VARCHAR2(32)
16. var SQLTYP NUMBER
17. var TID NUMBER
18.
19. --SID: 258,16699
20. exec :ACCEPTDIS:='ACCEPTDISABLED';
21. exec :BENAME:='EXEC_42756';
22. exec :EENAME:='EXEC_43638';

23. exec :IMPLTYP:='IMPLEMENTATION';
24. exec :PROFILETYP:='SQL PROFILE';
25. exec :SQLTYP:=7
26. exec :TID:=29631
27.
28. --SID: 1790,51175
29. var ACCEPTDIS VARCHAR2(32)
30. var BENAME VARCHAR2(32)
31. var EENAME VARCHAR2(32)
32. var IMPLTYP VARCHAR2(32)
33. var PROFILETYP VARCHAR2(32)
34. var SQLTYP NUMBER
35. var TID NUMBER
36.
37. --SID: 1790,51175
38. exec :ACCEPTDIS:='ACCEPTDISABLED';
39. exec :BENAME:='EXEC_42756';
40. exec :EENAME:='EXEC_43638';
41. exec :IMPLTYP:='IMPLEMENTATION';
42. exec :PROFILETYP:='SQL PROFILE';
43. exec :SQLTYP:=7
44. exec :TID:=29631
45.
46.
47. ------------- SQL Text -------------48.
49. SELECT /*+ leading(oe f r l) */

50.

/* STN_REPT_TOP_PROF */

51.

xmlelement(

52.

"top_profiles",

53.

xmlagg(xmlelement("obj_id", object_id)))

54.

FROM

(SELECT task_id, exec_name, exec_id, exec_start, object_id, sql_

id,
55.

parsing_schema, phv, obj_attr8

56.

FROM

(SELECT /*+ cardinality(o 5999) leading(e o) */

57.

e.task_id task_id,

58.

e.execution_name exec_name,

59.

e.execution_id exec_id,

60.

e.execution_start exec_start,

61.

o.id object_id,

62.

o.attr1 sql_id,

63.

o.attr3 parsing_schema,

64.

to_number(nvl(o.attr5, '0'))

65.

nvl(o.attr8,0) obj_attr8,

66.

row_number() over

67.

phv,

(partition by o.attr1

68.

order by

69.

bitand(o.attr7, 32) asc,
e.execution_start desc)

70.

rn

71.

FROM

(SELECT e.task_id, e.name execution_name, e.id execu

tion_id,
72.
73.
74.
75.

e.exec_start execution_start, e.status status#
FROM (SELECT

task_id,
min(execution_name) keep (dense_rank first order by
execution_start) bename,

76.

max(execution_name) keep (dense_rank last order by

77.

execution_start) eename,

78.

min(execution_start) bestart,

79.

max(execution_start) eestart

80.

FROM

(SELECT task_id, name execution_name,

81.

exec_start execution_start

82.

FROM

wri$_adv_executions

83.

WHERE

task_id = :tid and

84.

name in (:bename, :eename))

85.

GROUP BY task_id) r,

86.

wri$_adv_executions e

87.
88.
89.

WHERE e.task_id = r.task_id and

90.

e.exec_start >= bestart and

91.

e.exec_start <= eestart and

92.

e.status IN (3, 4) and

93.

(bename <> eename OR e.name = bename)) e

94.

wri$_adv_objects o

95.

WHERE

/* e */,

o.task_id = e.task_id AND

96.

o.exec_name = e.execution_name AND

97.

o.type = :sqltyp)

98.
99.

WHERE rn = 1) oe

/* oe */,

wri$_adv_findings f,

100.

wri$_adv_recommendations r,

101.

wri$_adv_rationale l

102.

WHERE

oe.task_id = f.task_id AND oe.exec_name = f.exec_name AND

103.

oe.object_id = f.obj_id AND f.task_id = r.task_id AND

104.

f.exec_name = r.exec_name AND f.id = r.finding_id AND

105.

l.task_id = r.task_id AND l.exec_name = r.exec_name AND

106.

l.rec_id = r.id AND

107.

r.type = :profiletyp AND l.type = :impltyp AND

108.

l.attr1 = :acceptdis AND

109.

NOT EXISTS (SELECT 1

110.

FROM

dba_sql_profiles p

111.

WHERE

p.task_id = r.task_id AND

112.

p.task_exec_name = r.exec_name AND

113.

p.task_obj_id = oe.object_id AND

114.

p.task_fnd_id = r.finding_id AND

115.

p.task_rec_id = r.id)

116.
117.
118.

------------- SQL Plan (Plan Hash Value:589376886) --------------

119.
120.

0

( )SELECT STATEMENT Optimizer=ALL_ROWS

121.

1

(0) SORT (AGGREGATE)

122.

2

(1)

123.

3

(2)

124.

4

(3)

NESTED LOOPS (Cost=11 Card=159 rows Bytes=0/93)

125.

5

(4)

NESTED LOOPS (Cost=9 Card=608 rows Bytes=0/54)

126.

#6

(5)

127.
0/123)

#7

(6)

8

(7)

128.

NESTED LOOPS (ANTI) (Cost=30 Card=11 rows Bytes=0/129)
NESTED LOOPS (Cost=26 Card=11 rows Bytes=0/129)

VIEW (Cost=8 Card=268 rows Bytes=0/31)
WINDOW (SORT PUSHED RANK) (Cost=8 Card=489 rows Bytes=

NESTED LOOPS

129.

9

(8)

NESTED LOOPS (Cost=7 Card=1667 rows Bytes=0/123)

130.

10

(9)

NESTED LOOPS (Cost=5 Card=33 rows Bytes=0/84)

131.

11

(10)

132.

12

(11)

VIEW (Cost=3 Card=1 rows Bytes=0/57)
SORT (GROUP BY) (Cost=3 Card=1 rows Bytes=0/24)

133.
13 (12)
TABLE ACCESS (BY INDEX ROWID) OF 'WRI$_ADV_EXECU
TIONS' (TABLE) (Cost=3 Card=2 rows Bytes=0/24)
134.
*#14 (13)
INDEX (RANGE SCAN) OF 'WRI$_ADV_EXECS_PK' (INDE
X (UNIQUE)) (Cost=2 Card=2 rows Bytes=0/)
135.
#15 (10)
TABLE ACCESS (BY INDEX ROWID) OF 'WRI$_ADV_EXECUTI
ONS' (TABLE) (Cost=2 Card=33 rows Bytes=0/27)
136.
*16 (15)
INDEX (RANGE SCAN) OF 'WRI$_ADV_EXECS_IDX_03' (IN
DEX) (Cost=1 Card=33 rows Bytes=0/)
137.
*17
(9)
INDEX (RANGE SCAN) OF 'WRI$_ADV_OBJECTS_IDX_01' (IN
DEX (UNIQUE)) (Cost=1 Card=1667 rows Bytes=0/)
138.
#18
(8)
TABLE ACCESS (BY INDEX ROWID) OF 'WRI$_ADV_OBJECTS'
(TABLE) (Cost=2 Card=1634 rows Bytes=0/273)
139.
*19
(5)
INDEX (RANGE SCAN) OF 'WRI$_ADV_FINDINGS_IDX_02' (INDEX
(UNIQUE)) (Cost=1 Card=608 rows Bytes=0/23)
140.
#20
(4)
TABLE ACCESS (BY INDEX ROWID) OF 'WRI$_ADV_RECOMMENDATIO
NS' (TABLE) (Cost=2 Card=159 rows Bytes=0/39)
141.
*21 (20)
INDEX (RANGE SCAN) OF 'WRI$_ADV_RECS_IDX_02' (INDEX (UN
IQUE)) (Cost=1 Card=345 rows Bytes=0/)
142.
#22
(3)
TABLE ACCESS (BY INDEX ROWID) OF 'WRI$_ADV_RATIONALE' (TA
BLE) (Cost=15 Card=11 rows Bytes=0/36)
143.
*23 (22)
INDEX (RANGE SCAN) OF 'WRI$_ADV_RATIONALE_PK' (INDEX (UN
IQUE)) (Cost=3 Card=27293304 rows Bytes=0/)
144.
24
ows Bytes=0/)

(2)

VIEW PUSHED PREDICATE OF 'VW_SQ_1' (VIEW) (Cost=4 Card=0 r

145.

25

(24)

NESTED LOOPS (Cost=4 Card=0 rows Bytes=0/240)

146.

26

(25)

NESTED LOOPS (Cost=4 Card=0 rows Bytes=0/204)

147.

*27

(26)

HASH JOIN (Cost=4 Card=0 rows Bytes=0/168)

148.
#28 (27)
TABLE ACCESS (BY INDEX ROWID) OF 'SQLOBJ$AUXDATA' (TAB
LE) (Cost=2 Card=0 rows Bytes=0/462)
149.
*29 (28)
INDEX (RANGE SCAN) OF 'I_SQLOBJ$AUXDATA_TASK' (INDEX)
(Cost=1 Card=0 rows Bytes=0/)

150.
*#30 (27)
INDEX (SKIP SCAN) OF 'SQLOBJ$_PKEY' (INDEX (UNIQUE)) (
Cost=1 Card=0 rows Bytes=0/322)
151.
))

*31

(26)

152.

*32

(25)

INDEX (UNIQUE SCAN) OF 'I_SQL$TEXT_PKEY' (INDEX (UNIQUE

INDEX (UNIQUE SCAN) OF 'I_SQL$_PKEY' (INDEX (UNIQUE))

153.
154.
------------- Predicate Information (Plan Hash Value:589376886) ------------155.
156.

6 Filter: "RN"=1

157.
7 Filter: ROW_NUMBER() OVER ( PARTITION BY "O"."ATTR1" ORDER BY BITAND(
"O"."ATTR7",32),INTERNAL_FUNCTION("E"."EXEC_START") DESC )<=1
158.

14 Access: "TASK_ID"=:TID

159.

14 Filter: ("NAME"=:BENAME OR "NAME"=:EENAME)

160.
15 Filter: (INTERNAL_FUNCTION("E"."STATUS") AND ("BENAME"<>"EENAME" OR "
E"."NAME"="BENAME"))
161.
16 Access: "E"."TASK_ID"="R"."TASK_ID" AND "E"."EXEC_START">="BESTART" A
ND "E"."EXEC_START"<="EESTART"
162.

17 Access: "O"."TASK_ID"="E"."TASK_ID" AND "O"."EXEC_NAME"="E"."NAME"

163.

18 Filter: "O"."TYPE"=:SQLTYP

164.
19 Access: "TASK_ID"="F"."TASK_ID" AND "EXEC_NAME"="F"."EXEC_NAME" AND "
OBJECT_ID"="F"."OBJ_ID"
165.

20 Filter: "R"."TYPE"=:PROFILETYP

166.
21 Access: "F"."TASK_ID"="R"."TASK_ID" AND "F"."EXEC_NAME"="R"."EXEC_NAM
E" AND "F"."ID"="R"."FINDING_ID"
167.
22 Filter: ("L"."TYPE"=:IMPLTYP AND "L"."ATTR1"=:ACCEPTDIS AND "L"."EXEC
_NAME"="R"."EXEC_NAME" AND "L"."REC_ID"="R"."ID")
168.

23 Access: "L"."TASK_ID"="R"."TASK_ID"

169.
27 Access: "SO"."SIGNATURE"="AD"."SIGNATURE" AND "SO"."CATEGORY"="AD"."C
ATEGORY"
170.

28 Filter: "AD"."OBJ_TYPE"=1

171.
29 Access: "AD"."TASK_ID"="R"."TASK_ID" AND "AD"."TASK_EXEC_NAME"="R"."E
XEC_NAME" AND "AD"."TASK_OBJ_ID"="OBJECT_ID" AND "AD"."TASK_FND_ID"="R"."FINDIN
G_ID" AND "AD"."TASK_REC_ID"="R"."ID"

172.

30 Access: "SO"."OBJ_TYPE"=1

173.

30 Filter: "SO"."OBJ_TYPE"=1

174.

31 Access: "SO"."SIGNATURE"="ST"."SIGNATURE"

175.

32 Access: "SO"."SIGNATURE"="SQ"."SIGNATURE"

176.
177.

------------- Plan Loading (Plan Hash Value:589376886) --------------

178.
179.
22: TABLE ACCESS BY INDEX ROWID
###########################(89.47%)

##################

180.

#####(10.53%)

23: INDEX RANGE SCAN

181.
182.

------------- Waits Events (Plan Hash Value:589376886) --------------

183.
184.

ON CPU on SYS.WRI$_ADV_RECS_IDX_02(INDEX)
#####(9.65%)

185.
186.

------------- Statistics Data --------------

187.
188.

Loads: 1

189.

Load Versions: 1

190.

First Load Time: 2014-03-12/22:46:24

191.

Last Load Time: 2014-03-12/22:46:24

192.

User Openings: 0

193.

Parse Calls: 11

194.

Executions: 11

195.

Sorts(Average): 2

196.

Fetches(Average): 1

197.

Disk Reads(Average): .545

198.

Buffer Gets(Average): 1416843.364

199.

Elapsed Time(Average): 10.507 seconds

200.

CPU Time(Average): 10.501 seconds

201.

Run Time Memory(Average): .005M

202.

PGA Size(Maximum): .015G

203.

Temp Space(Maximum): 0G

Note: This version works in 11gR2. You may need to remove the part containing the
not existing views/columns in other DB versions, e.g. v$sql_monitor.
Download the latest verstion at
here: http://www.HelloDBA.com/download/showplan.zip

Oracle SQL Hints --- Model Query And
Partition Hints
Model Query Hints
MODEL_MIN_ANALYSIS
Usage: MODEL_MIN_ANALYSIS
Description: Instructs the optimizer to do minimum transformation analysis on the main
query when performing 用 query transformation on Model Query.
Trace below two queries with/without this hint:

HELLODBA.COM>alter session set events 'TRACE[RDBMS.SQL_Compiler.*]';

Session altered.

HELLODBA.COM>explain plan for

2

SELECT /*+qb_name(m) no_merge(@inv) NO_MERGE(@"SEL$2")*/status, s

3
FROM (select /*+qb_name(inv) no_merge(v)*/o.owner, o.status,
o.object_name, o.created, t.tablespace_name from v_objects_sys o, t_tables t
where o.owner=t.owner and o.object_name=t.table_name) q
4

WHERE q.created < :A

5

MODEL RETURN UPDATED ROWS

6

PARTITION BY (status)

7

DIMENSION BY (owner)

8

MEASURES (object_name v, 1 s)

9

RULES

10

(s[any] = count(v) over (partition by status));

... ...

HELLODBA.COM>explain plan for
2 SELECT /*+qb_name(m) MODEL_MIN_ANALYSIS no_merge(@inv)
NO_MERGE(@"SEL$2")*/status, s
3
FROM (select /*+qb_name(inv) no_merge(v)*/o.owner, o.status,
o.object_name, o.created, t.tablespace_name from v_objects_sys o, t_tables t
where o.owner=t.owner and o.object_name=t.table_name) q
4

WHERE q.created < :A

5

MODEL RETURN UPDATED ROWS

6

PARTITION BY (status)

7

DIMENSION BY (owner)

8

MEASURES (object_name v, 1 s)

9

RULES

10

(s[any] = count(v) over (partition by status));

Comparing the trace content, we can find the optimizer performed simple filter push
analysis:

FPD: Considering simple filter push (pre rewrite) in query block M (#0)
FPD:

Current where clause predicates

??

try to generate transitive predicate from check constraints for query block M (#0)
finally:

??

kkqfppRelFilter: Not pushing filter predicates in query block SEL$21876068 (#0)
because no predicate to push
FPD: Considering simple filter push (pre rewrite) in query block SEL$21876068 (#0)
FPD: Current where clause predicates "T_OBJECTS"."OWNER"="T"."OWNER" AND
"T_OBJECTS"."OBJECT_NAME"="T"."TABLE_NAME" AND "T_OBJECTS"."OWNER"='SYS' AND
"T_OBJECTS"."CREATED"<:B1 AND "T"."OWNER"='SYS'
MODEL_NO_ANALYSIS
Usage: MODEL_NO_ANALYSIS
Description: Prevents the optimizer to do transformation analysis on the main query when
performing. We can compare the optimizer tracing records to confirm the effect of this hint.
MODEL_PUSH_REF
Usage: MODEL_PUSH_REF
Description: Unknown. It might instruct the optimizer to push the predication in the main
model to reference model.
NO_MODEL_PUSH_REF
Usage: NO_MODEL_PUSH_REF
Description: Unknown. It might prevent the optimizer to push the predication in the main
model to reference model.

MODEL_COMPILE_SUBQUERY
Usage: MODEL_COMPILE_SUBQUERY
Description: Unknown. It might be used for model query transformation.
MODEL_DONTVERIFY_UNIQUENESS
Usage: MODEL_DONTVERIFY_UNIQUENESS
Description: Unknown. It might be used for model query transformation.
MODEL_DYNAMIC_SUBQUERY
Usage: MODEL_DYNAMIC_SUBQUERY
Description: Unknown. It might be used for model query transformation.

Partitioning Hints
X_DYN_PRUNE
Usage: X_DYN_PRUNE
Description: Instructs the SQL executor to using the result of sub query to prune the
partitions dynamically.

HELLODBA.COM>alter session set tracefile_identifier = 'hash_X_DYN_PRUNE(10128)';

Session altered.

HELLODBA.COM>alter session set events '10128 trace name context forever, level
31';

Session altered.

HELLODBA.COM>select /*+use_hash(tr t2) X_DYN_PRUNE*/tr.* from t_objects_range tr,
t_tables t2 where tr.owner=t2.owner and tr.object_name=t2.table_name and
t2.tablespace_name='USERS';

… …

HELLODBA.COM>exec sql_explain('select /*+use_hash(tr t2) X_DYN_PRUNE*/tr.* from
t_objects_range tr, t_tables t2 where tr.owner=t2.owner and
tr.object_name=t2.table_name and t2.tablespace_name=''USERS''', 'BASIC OUTLINE');

--------------------------------------------------------| Id | Operation

| Name

|

--------------------------------------------------------|

0 | SELECT STATEMENT

|

|

|

1 |

|

|

|

2 |

| :BF0000

|

|

3 |

|

4 |

|

5 |

|

6 |

HASH JOIN
PART JOIN FILTER CREATE

TABLE ACCESS BY INDEX ROWID| T_TABLES
INDEX RANGE SCAN

| T_TABLES_IDX3

PARTITION RANGE JOIN-FILTER |
TABLE ACCESS FULL

|
|
|

| T_OBJECTS_RANGE |

---------------------------------------------------------

From the trace records of 10128 event, we got below entries:

kkpapDAExtSQuerySLvl strings sql1 SELECT distinct
TBL$OR$IDX$PART$NUM("T_OBJECTS_RANGE", 0, sql2 "OWNER", "OBJECT_NAME") FROM
(SELECT "A1"."OWNER" "OWNER", "A1"."TABLE_NAME" "OBJECT_NAME" FROM "T_TABLES" "A1"
WHERE "A1"."TABLESPACE_NAME"='USERS') ORDER BY 1
SUBQUERY_PRUNING
Usage: SUBQUERY_PRUNING([<@Block>] <Table> PARTITION)
Description: Instructs the optimizer to using sub query to prune the partitions dynamically.

HELLODBA.COM>exec sql_explain('select /*+ use_merge(tr t2) SUBQUERY_PRUNING(tr
PARTITION)*/tr.* from t_objects_range tr, t_tables t2 where tr.owner=t2.owner and
tr.object_name=t2.table_name and t2.tablespace_name=''SYSTEM''', 'BASIC');

------------------------------------------------------| Id | Operation

| Name

|

------------------------------------------------------|

0 | SELECT STATEMENT

|

|

|

1 |

MERGE JOIN

|

|

|

2 |

SORT JOIN

|

|

|

3 |

|

4 |

|

5 |

|

6 |

|

7 |

|

8 |

|

9 |

VIEW
HASH JOIN

| index$_join$_002 |
|

|

INDEX RANGE SCAN

| T_TABLES_IDX3

|

INDEX FAST FULL SCAN

| T_TABLES_PK

|

|

|

SORT JOIN

PARTITION RANGE SUBQUERY|
TABLE ACCESS FULL

| T_OBJECTS_RANGE

|
|

-------------------------------------------------------

From the trace records of 10128 event, we got below entries:

SQL text = text = SELECT distinct TBL$OR$IDX$PART$NUM("T_OBJECTS_RANGE",
0, "OWNER", "OBJECT_NAME") FROM (SELECT "T2"."OWNER" "OWNER", "T2"."TABLE_NAME"
"OBJECT_NAME" FROM "T_TABLES" "T2" WHERE "T2"."TABLESPACE_NAME"='SYSTEM') ORDER BY
1}
NO_SUBQUERY_PRUNING
Usage: NO_SUBQUERY_PRUNING([<@Block>] <Table>)

Description: Prevents the optimizer to using sub query to prune the partitions dynamically.

HELLODBA.COM>exec sql_explain('select /*+NO_SUBQUERY_PRUNING(O PARTITION)
LEADING(u)*/o.* from t_objects_range o, t_tables t, t_users u where
o.owner=t.owner and o.object_name=t.table_name and o.owner=u.username and
t.tablespace_name=''USERS'' and u.user_id<10', 'BASIC OUTLINE');

---------------------------------------------------------| Id | Operation

| Name

|

---------------------------------------------------------|

0 | SELECT STATEMENT

|

|

|

1 |

|

|

|

2 |

NESTED LOOPS

|

|

|

3 |

HASH JOIN

|

|

|

4 |

|

5 |

|

6 |

|

7 |

|

8 |

|

9 |

NESTED LOOPS

TABLE ACCESS BY INDEX ROWID| T_USERS
INDEX RANGE SCAN
PARTITION RANGE ALL
TABLE ACCESS FULL
INDEX UNIQUE SCAN
TABLE ACCESS BY INDEX ROWID

| T_USERS_PK

|
|

|

|

| T_OBJECTS_RANGE |
| T_TABLES_PK

|

| T_TABLES

|

----------------------------------------------------------

Oracle SQL Hints --- Other Hints
Other Hints
RELATIONAL
Usage: RELATIONAL([<@Block>] <Table>)

Description: Instructs the optimizer to convert the Object to a relational table, similar to
RELATIONAL function.

HELLODBA.COM>desc xmltable
Name

Null?

Type

----------------------------------------- --------- --------TABLE of PUBLIC.XMLTYPE

HELLODBA.COM>select * from xmltable;

SYS_NC_ROWINFO$
-----------------------------------------------------------------------------------------------------<other_xml>
<outline_data>
<hint>
<IGNORE_OPTIM_EMBEDDED_HINTS/>
</hint>
... ...
</outline_data>
</other_xml>

1 row selected.

HELLODBA.COM>select /*+ relational(x) */* from xmltable x;

SYS_NC_OID$

XMLDATA

----------------------------------------------------------------------------------------------------5477ABC43C2D4A85917F7328AA961884
<other_xml><outline_data><hint><IGNORE_OPTIM_EMBEDDED_HINTS></IGNORE_OPTIM_EMBED
DED_HINTS></hint><hint><OPTIMIZER_FEATURES_ENABLE>10.2.0.3</OPTIMIZER_FEATURES_E
NABLE></hint><hint><![CDATA[ALL_ROWS]]></hint><hint><OUTLINE_LEAF>"SEL$3BA1AD7C"
… …

MONITOR
Usage: MONITOR
Description: Instruct Oracle monitor the running status of the statement, regardless of
whether it fulfills the criteria (Parallel Query or Running for more than 5 seconds) or not.

HELLODBA.COM>show parameter CONTROL_MANAGEMENT_PACK_ACCESS

NAME

TYPE

VALUE

------------------------------------ ----------- -----------------------------control_management_pack_access

string

DIAGNOSTIC+TUNING

HELLODBA.COM>select /*+ monitor */count(*) from t_users u;

COUNT(*)
---------31

HELLODBA.COM>select sql_text, status from v$sql_monitor where sql_text like

'%monitor%';

SQL_TEXT

STATUS

------------------------------------------------------------ ------------------select /*+ monitor */count(*) from t_users u

DONE (ALL ROWS)

NO_MONITOR
Usage: NO_MONITOR
Description: Prevent Oracle monitor the running status of the statement, regardless of
whether it fulfills the criteria (Parallel Query or Running for more than 5 seconds) or not.

HELLODBA.COM>select /*+ no_monitor parallel(o 2) full(o) */ /*identifier*/
count(*) from t_objects o;

COUNT(*)
---------72116

HELLODBA.COM>select sql_text, status from v$sql_monitor where sql_text like
'%identifier%';

no rows selected
NESTED_TABLE_FAST_INSERT
Usage: NESTED_TABLE_FAST_INSERT
Description: Instructs SQL executor to insert data into nested table in fast mode. From the
trace content of 10046 event, the data was inserted in batch.

HELLODBA.COM>CREATE OR REPLACE TYPE simple_type AS TABLE OF VARCHAR2(30);

2

/

Type created.

HELLODBA.COM>CREATE TABLE t_nt_table (a NUMBER, b simple_type) NESTED TABLE b
STORE AS t_nt_b;

Table created.

HELLODBA.COM>INSERT /*+ */ INTO t_nt_table select object_id,
simple_type(object_name) from t_objects;

72116 rows created.

Elapsed: 00:00:18.77

HELLODBA.COM>INSERT /*+ NESTED_TABLE_FAST_INSERT */ INTO t_nt_table select
object_id, simple_type(object_name) from t_objects;

72116 rows created.

Elapsed: 00:00:07.79
NESTED_TABLE_GET_REFS
Usage: NESTED_TABLE_GET_REFS
Description: With this hint, user can access to nested table directly.

HELLODBA.COM>select /*+ */count(*) from T_NT_B;
select /*+ */count(*) from T_NT_B
*
ERROR at line 1:
ORA-22812: cannot reference nested table column's storage table

HELLODBA.COM>select /*+ nested_table_get_refs */count(*) from T_NT_B;

COUNT(*)
---------72116
NESTED_TABLE_SET_SETID
Usage: NESTED_TABLE_SET_SETID
Description: With this hint, user can access to nested table directly.

HELLODBA.COM>select /*+ NESTED_TABLE_SET_SETID */count(*) from T_NT_B;

COUNT(*)
---------72116
NO_MONITORING
Usage: NO_MONITORING
Description: Prevent Oracle monitor the column usage in predication, consequently, the
dictionary table col_usage$ will not be updated by the execution of the statement.

HELLODBA.COM>select like_preds from sys.SQLT$_DBA_COL_USAGE_V where owner ='DEMO'

and table_name = 'T_TABLES' and column_name = 'TABLE_NAME';

LIKE_PREDS
---------18

HELLODBA.COM>select /*run(7)*/count(*) from t_tables where 7=7 and table_name like
'T%';

COUNT(*)
---------30

HELLODBA.COM>exec dbms_stats.gather_table_stats('DEMO', 'T_TABLES');

PL/SQL procedure successfully completed.

HELLODBA.COM>select like_preds from sys.SQLT$_DBA_COL_USAGE_V where owner ='DEMO'
and table_name = 'T_TABLES' and column_name = 'TABLE_NAME';

LIKE_PREDS
---------19

HELLODBA.COM>select /*+ no_monitoring *//*run(8)*/count(*) from t_tables where

8=8 and table_name like 'T%';

COUNT(*)
---------30

HELLODBA.COM>exec dbms_stats.gather_table_stats('DEMO', 'T_TABLES');

PL/SQL procedure successfully completed.

HELLODBA.COM>select like_preds from sys.SQLT$_DBA_COL_USAGE_V where owner ='DEMO'
and table_name = 'T_TABLES' and column_name = 'TABLE_NAME';

LIKE_PREDS
---------19
NO_SQL_TUNE
Usage: NO_SQL_TUNE
Description: Prevent the optimizer to do SQL tuning on the statement.

HELLODBA.COM>select /* No_TUNE(2) *//*+NO_SQL_TUNE*/count(*) from t_users;

COUNT(*)
---------31

… …
HELLODBA.COM>exec :exec_name := dbms_sqltune.execute_tuning_task (:task_name,
'EXEC_'||substr(:task_name, length(:task_name)-4));

PL/SQL procedure successfully completed.

HELLODBA.COM>select dbms_sqltune.report_tuning_task (:task_name) from dual;
... ...
ADDITIONAL INFORMATION SECTION
-------------------------------------------------------------------------- 不支持的 SQL 语句类型。

RESTRICT_ALL_REF_CONS
Usage: RESTRICT_ALL_REF_CONS
Description: Restricts all cascaded operations caused by referencing constraints in the
transactions.

HELLODBA.COM>select owner, table_name, constraint_name, r_owner,
r_constraint_name, delete_rule from dba_constraints where constraint_name =
'T_C_FK';

OWNER
AME

TABLE_NAME
DELETE_RULE

CONSTRAINT_NAME

R_OWNER

R_CONSTRAINT_N

-------------- ----------------- -------------------- --------------------------------- --------DEMO

T_C
CASCADE

T_C_FK

DEMO

T_P_PK

HELLODBA.COM>delete /*+RESTRICT_ALL_REF_CONS*/from t_p where a=3;

1 row deleted.

HELLODBA.COM>select count(a) from t_c where a=3;

COUNT(A)
---------1

HELLODBA.COM>commit;
commit
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-02292: integrity constraint (DEMO.T_C_FK) violated - child record found
USE_HASH_AGGREGATION
Usage: USE_HASH_AGGREGATION([<@Block>])
Description: Instructs the optimizer using hash algorithm to perform aggregation operations.

HELLODBA.COM>alter session set "_gby_hash_aggregation_enabled"=false;

Session altered.

HELLODBA.COM>exec sql_explain('select /*+qb_name(M) USE_CONCAT(@M)*/owner,
count(1) from t_objects o group by owner', 'T
YPICAL OUTLINE');
Plan hash value: 87103648

--------------------------------------------------------------------------------------| Id | Operation
Time
|

| Name

| Rows | Bytes | Cost (%CPU)|

--------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
00:00:02 |
|
1 | HASH GROUP BY
00:00:02 |

|

|

|

23 |

|

23 |

|
2 |
INDEX FAST FULL SCAN| T_OBJECTS_IDX8 | 72116 |
00:00:02 |

138 |

138 |

422K|

196

196

185

(8)|

(8)|

(2)|

--------------------------------------------------------------------------------------NO_USE_HASH_AGGREGATION
Usage: NO_USE_HASH_AGGREGATION([<@Block>])
Description: Prevents the optimizer using hash algorithm to perform aggregation operations.

HELLODBA.COM>exec sql_explain('select /*+qb_name(M)
NO_USE_HASH_AGGREGATION(@M)*/owner, count(1) from t_objects o group by owner',
'TYPICAL OUTLINE');
Plan hash value: 49003928

----------------------------------------------------------------------------------

-----| Id | Operation
Time
|

| Name

| Rows | Bytes | Cost (%CPU)|

--------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
00:00:02 |

|

|
1 | SORT GROUP BY
00:00:02 |

|

|

23 |

|

23 |

|
2 |
INDEX FAST FULL SCAN| T_OBJECTS_IDX8 | 72116 |
00:00:02 |

138 |

138 |

422K|

196

196

185

(8)|

(8)|

(2)|

--------------------------------------------------------------------------------------BYPASS_RECURSIVE_CHECK
Usage: BYPASS_RECURSIVE_CHECK
Description: Unknown. It might instruct the parser not do recursive checking. It could be
observed in the internal statement generated by Materialized View updating.
Demo:

HELLODBA.COM>alter session set sql_trace=true;

Session altered.

HELLODBA.COM>exec dbms_mview.refresh(list => 'MV_TABLES');

PL/SQL procedure successfully completed.

We got below statement from the tracing content.

INSERT /*+ BYPASS_RECURSIVE_CHECK */ INTO
"DEMO"."MV_TABLES"("OWNER","TABLE_NAME","TABLESPACE_NAME","CREATED","LAST_DDL_TIME
") SELECT
"T"."OWNER","T"."TABLE_NAME","T"."TABLESPACE_NAME","O"."CREATED","O"."LAST_DDL_TIM
E" FROM "T_TABLES" "T","T_OBJECTS" "O" WHERE "T"."OWNER"="O"."OWNER" AND
"T"."TABLE_NAME"="O"."OBJECT_NAME" AND "O"."OBJECT_TYPE"=:"SYS_B_0" AND
"T"."TABLESPACE_NAME" IS NOT NULL

BYPASS_UJVC
Usage: BYPASS_UJVC
Description: Unknown. It might instruct parser not check unique constraint for the join view.
It could be observed in the internal statement generated by Materialized View
updating.
We got below statement from the trace file generated in previous demo.

update /*+ BYPASS_UJVC */
( select s.status status
from snap$ s,
snap_reftime$ r
where s.sowner = r.sowner and s.vname = r.vname
and
r.mowner = :1 and r.master = :2 and s.mlink IS NULL
and
bitand(s.status,16) = 0 and r.instsite =0 and s.instsite =0) v
set status =
status + 16;
DOMAIN_INDEX_FILTER
Usage: DOMAIN_INDEX_FILTER([<@Block>] <Table> [( <Index>)]) or
DOMAIN_INDEX_FILTER([<@Block>] <Table> [( <Indexed Columns>)])
Description: Instructs the optimizer the push filter to Composite Domain Index.

HELLODBA.COM>exec sql_explain('SELECT /*+ domain_index_filter(t t_tables_dix03) */
* FROM t_tables t WHERE CONTAINS(owner, ''aaa'',1)>0 AND status = ''VALID''',
'TYPICAL');

--------------------------------------------------------------------------------------------| Id | Operation
(%CPU)| Time
|

| Name

| Rows | Bytes | Cost

--------------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
00:00:01 |

|

|
1 | TABLE ACCESS BY INDEX ROWID| T_TABLES
00:00:01 |
|*
|

2 |
|

|

1 |

241 |

4

(0)|

|

1 |

241 |

4

(0)|

DOMAIN INDEX
| T_TABLES_DIX03
|
4 (0)| 00:00:01 |

---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("CTXSYS"."CONTAINS"("OWNER",'aaa',1)>0)
filter("STATUS"='VALID')
NO_DOMAIN_INDEX_FILTER
Usage: NO_DOMAIN_INDEX_FILTER([<@Block>] <Table> [( <Index>)]) or
NO_DOMAIN_INDEX_FILTER([<@Block>] <Table> [( <Indexed Columns>)])
Description: Prevents the optimizer the push filter to Composite Domain Index.

HELLODBA.COM>exec sql_explain('SELECT /*+ no_domain_index_filter(t t_tables_dix03)
*/ * FROM t_tables t WHERE CONTAINS(owner, ''aaa'',1)>0 AND status = ''VALID''',
'TYPICAL');

--------------------------------------------------------------------------------------------| Id | Operation
(%CPU)| Time
|

| Name

| Rows | Bytes | Cost

----------------------------------------------------------------------------------

-----------|
0 | SELECT STATEMENT
00:00:01 |

|

|* 1 | TABLE ACCESS BY INDEX ROWID| T_TABLES
00:00:01 |
|*
|

2 |
|

DOMAIN INDEX
|
4

|

1 |

241 |

4

(0)|

|

1 |

241 |

4

(0)|

| T_TABLES_DIX03
(0)| 00:00:01 |

---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("STATUS"='VALID')
2 - access("CTXSYS"."CONTAINS"("OWNER",'aaa',1)>0)

DOMAIN_INDEX_SORT
Usage: DOMAIN_INDEX_SORT
Description: Instructs the optimizer the push sorting columns to Composite Domain Index.

HELLODBA.COM>exec sql_explain('SELECT /*+ domain_index_sort */ * FROM t_tables t
WHERE CONTAINS(tablespace_name, ''aaa'',1)>0 ORDER BY table_name, score(1) desc',
'TYPICAL');
Plan hash value: 991332243

--------------------------------------------------------------------------------------------| Id | Operation

| Name

| Rows | Bytes | Cost

(%CPU)| Time

|

--------------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
00:00:01 |

|

|
1 | TABLE ACCESS BY INDEX ROWID| T_TABLES
00:00:01 |
|*
|

2 |
|

DOMAIN INDEX
|
4

|

1 |

241 |

5 (20)|

|

1 |

241 |

5 (20)|

| T_TABLES_DIX02
(0)| 00:00:01 |

---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("CTXSYS"."CONTAINS"("TABLESPACE_NAME",'aaa',1)>0)

NO_DOMAIN_INDEX_ SORT
Usage: NO_DOMAIN_INDEX_ SORT
Description: Prevents the optimizer the push sorting columns to Composite Domain Index.

HELLODBA.COM>exec sql_explain('SELECT /*+ no_domain_index_sort */ * FROM t_tables
t WHERE CONTAINS(tablespace_name, ''aaa'',1)>0 ORDER BY table_name, score(1)
desc', 'TYPICAL');

---------------------------------------------------------------------------------------------| Id | Operation

| Name

| Rows | Bytes | Cost

(%CPU)| Time

|

---------------------------------------------------------------------------------------------|
|

0 | SELECT STATEMENT
5 (20)| 00:00:01 |

|
|

1 | SORT ORDER BY
5 (20)| 00:00:01 |

|
|

2 |
4

|*
|

3 |

|

|

|

TABLE ACCESS BY INDEX ROWID| T_TABLES
(0)| 00:00:01 |

|

1 |

|

|

1 |

1 |

241

241

241

DOMAIN INDEX
| T_TABLES_DIX02
|
4 (0)| 00:00:01 |

----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

3 - access("CTXSYS"."CONTAINS"("TABLESPACE_NAME",'aaa',1)>0)

DST_UPGRADE_INSERT_CONV
Usage: DST_UPGRADE_INSERT_CONV
Description: With this hint, Oracle will add an internal function
(ORA_DST_CONVERT(INTERNAL_FUNCTION())) to modify the column defined as TIMESTAMP
WITH TIME ZONE when using package DBMS_DST to upgrade the time zone of the database.
NO_DST_UPGRADE_INSERT_CONV
Usage: NO_DST_UPGRADE_INSERT_CONV
Description: With this hint, Oracle will not add an internal function
(ORA_DST_CONVERT(INTERNAL_FUNCTION())) to modify the column defined as TIMESTAMP
WITH TIME ZONE when using package DBMS_DST to upgrade the time zone of the database.

STREAMS
Usage: STREAMS
Description: Unknown. It might instructs the SQL execution to transfer the data in stream.
DEREF_NO_REWRITE
Usage: DEREF_NO_REWRITE(<@Block>)
Description: Unknown. It might prevent the optimizer to rewrite the Materialized View
with BUILD DEFERRED option.
MV_MERGE
Usage: MV_MERGE
Description: Unknown. It might be used for CUBE.
EXPR_CORR_CHECK
Usage: EXPR_CORR_CHECK
Description: Unknown. It might instruct the parser to do referencing checking where
analyzing Expression Filter.
INCLUDE_VERSION
Usage: INCLUDE_VERSION
Description: Unknown. It could be observed from the internal statement generated by
Advanced Replication. It might be used to keep the compatibility when replicating data
among databases with different versions.
VECTOR_READ
Usage: VECTOR_READ
Description: Unknown. It might be used for Vector Filter in hash join.
VECTOR_READ_TRACE
Usage: VECTOR_READ_TRACE
Description: Unknown. It might be used for Vector Filter in hash join.

USE_WEAK_NAME_RESL
Usage: USE_WEAK_NAME_RESL
Description: Unknown. It might instructs the parser using the internal name instead the userdefined name to find Resource Location. It could be observed from the internal statements
generated statistics data gathering and Expression Filter.

select /*+ no_parallel(t) no_parallel_index(t) dbms_stats cursor_sharing_exact
use_weak_name_resl dynamic_sampling(0) no_monitoring no_substrb_pad */
count(*) from "DEMO"."T_OBJECTS" sample block ( 9.1911764706,1) t
NO_PARTIAL_COMMIT
Usage: NO_PARTIAL_COMMIT
Description: Unknown. It might be used to prevent the commit of internal recursive
transaction. It could be observed from the internal statements generated by maintenance
of the table with nested object.

HELLODBA.COM>alter session set events 'sql_trace wait=true, bind=true,
plan_stat=all_executions';

Session altered.

HELLODBA.COM>INSERT /*+ NESTED_TABLE_FAST_INSERT */ INTO t_nt_table select
object_id, simple_type(object_name) from t_objects;

... ...

We got below statement from the trace file.

INSERT /*+ NO_PARTIAL_COMMIT REF_CASCADE_CURSOR */ INTO
("NESTED_TABLE_ID","COLUMN_VALUE") VALUES(:1, :2)

"DEMO"."T_NT_B"

REF_CASCADE_CURSOR
Usage: REF_CASCADE_CURSOR
Description: Unknown. It might be used to prevent the commit of internal recursive
transaction. It could be observed from the internal statements generated by maintenance of
the table with nested object.
Refer to the demo of NO_PARTIAL_COMMIT
NO_REF_CASCADE
Usage: NO_REF_CASCADE
Description: Unknown. It might prevent the internal recursive statement to use the cascade
cursor.
SQLLDR
Usage: SQLLDR
Description: Unknown. It might be used in the internal statements generated by SQL*Loader.
SYS_RID_ORDER
Usage: SYS_RID_ORDER
Description: Unknown. It might be used in the internal statements generated by
maintenance of Materialized View.
OVERFLOW_NOMOVE
Usage: OVERFLOW_NOMOVE
Description: Unknown. It might prevent Oracle to move the data of other segment when
overflow occurs due to partition splitting.
LOCAL_INDEXES
Usage: LOCAL_INDEXES
Description: Unknown
MERGE_CONST_ON
Usage: MERGE_CONST_ON

Description: Unknown
QUEUE_CURR
Usage: QUEUE_CURR
Description: Unknown. It might be used for Advanced Queue.
CACHE_CB
Usage: CACHE_CB([<@Block>] <Table>)
Description: Unknown. It might be used for Advanced Queue.
Trace the process of DBMS_AQ.DEQUEUUE (delivery_mode is PERSISTENT), we got below
statement.

delete /*+ CACHE_CB("QUETABLET") */ from "DEMO"."QUETABLET" where rowid = :1;
QUEUE_ROWP
Usage: QUEUE_ROWP
Description: Unknown. It might be used for Advanced Queue.
BUFFER
Usage: BUFFER
Description: Unknown. It might be used for Advanced Queue.
NO_BUFFER
Usage: NO_BUFFER
Description: Unknown. It might be used for Advanced Queue.
BITMAP
Usage: BITMAP
Description: Unknown.。