Comments on: IN or EXIST or doesn’t it matter https://technology.amis.nl/2006/05/24/in-or-exist-or-doesnt-it-matter/ Friends of Oracle and Java Wed, 27 May 2015 22:00:57 +0000 hourly 1 http://wordpress.org/?v=4.2.2 By: Andrew Markiewicz https://technology.amis.nl/2006/05/24/in-or-exist-or-doesnt-it-matter/#comment-3322 Mon, 11 Sep 2006 17:57:29 +0000 http://technology.amis.nl/blog/?p=1210#comment-3322 Also of note is that the optimizer_index_cost_adj parameter is different in the two databases (unless that is a typo in the post).

optimizer_features_enable string 8.1.7
optimizer_index_caching integer 0
optimizer_index_cost_adj integer 10

optimizer_features_enable string 9.2.0
optimizer_index_caching integer 0
optimizer_index_cost_adj integer 100

OICA in the”8.1.7″ version calculates indexes as 10% of the cost making indexes more likely to be chosen.
That parameter should be the same for a comparison of the optimizer_features_enable parameter.

Andrew

]]>
By: Patrick Roozen https://technology.amis.nl/2006/05/24/in-or-exist-or-doesnt-it-matter/#comment-3321 Thu, 01 Jun 2006 22:31:14 +0000 http://technology.amis.nl/blog/?p=1210#comment-3321 Hi Andre,

In Jonathan Lewis’s book: Cost-Based Oracle Fundamentals on page 466 it also mentions that the optimizer_max_permutations will be 2000 when you set the optimizer_features_enable to 9.2.0. So that confirms what Alex says as well.

But as you know I have run the original query to be optimized in the developers test database with the parameter optimizer_features_enable set to 9.2.0 and it didn’t change the execution plan. (I do not have the output here anymore, but will provide the info if you can let me have the database so I can change the parameter back and forth)

I’m sad to see your comment “For some reason the DBA’s kept the optimizer_features_enable on 8.1.7 after the migration of the database. This prevented the optimizer from using new features like optimizing IN where clauses. The argument was that it could be possible that another value of this parameter could negatively impact performance. That could be true; but no one tested that; they just took tha assumption.” here because neither you nor me where there at that time. Therefor you cannot say that it wasn’t tested. You don’t know and neither do I. We just cannot find the reason anymore why it was left like that.

Do not think that changing that parameter is a silver bullet and will fix all the problems…
(as you know I pointed it out to you and we will change it to 9.2.0 but that has to be tested and thus will take it’s time)

When I have the chance I will run the original query (not your test query) on the database with the optimizer_features_enable set to 9.2.0 and back at 8.1.7 and will post the outcome of that here as well.

Keep up the good work 😉 and convince your collegues to use bind variables.

Patrick

]]>
By: Alex Gorbachev https://technology.amis.nl/2006/05/24/in-or-exist-or-doesnt-it-matter/#comment-3320 Fri, 26 May 2006 09:12:28 +0000 http://technology.amis.nl/blog/?p=1210#comment-3320 “Also the “optimizer_max_permutations” should have been set to 2000 (instead of 80000).”

I believe the default value optimizer_max_permutations is derived from optimizer_features_enable so setting it to 9.2.0 should “correct” optimizer_max_permutations as well.

]]>
By: karl https://technology.amis.nl/2006/05/24/in-or-exist-or-doesnt-it-matter/#comment-3319 Thu, 25 May 2006 15:13:11 +0000 http://technology.amis.nl/blog/?p=1210#comment-3319 hopefully my last posting;
— optimizer_features_enable string 8.1.7
As you told that was the reason. CBO has a lot on development on it. this makes sometimes hard to explain why a query takes a specific execution plan.
Karl

]]>
By: karl https://technology.amis.nl/2006/05/24/in-or-exist-or-doesnt-it-matter/#comment-3318 Thu, 25 May 2006 14:24:11 +0000 http://technology.amis.nl/blog/?p=1210#comment-3318 Hi again;
made a trip around a sea with my wife and now i know what to write about to finish my thougts.

Its all about determine thd DRIVING TABLE/QUERY. The Driving table is te table which the Row Source generator starts to retrieve data.
In RULE BASED times as RBO did not know about expected cardinality there were some fixed assumptions also using the IN and EXISTS operator.

Using an IN operator means in RBO Mode that the driving TABLE is the one accessed in the subquery. This helped when only a few rows where retrieved.

USING an EXISTS Operator in RBO mode means that the DRIVING TABLE/QUERY is the main query. this helps when only a few number of rows where retreived in the main query.

Now in the new world the CBO’s one, the DRIVING TABLE is choosen via expected number rows of the operation on this table. Using IN our EXISTS for CBO is meaningless for choosing the DRIVING TABLE/QUERY.

Using a rule hint of ths same table example demonstarate what i mean.

SQL> — RULE BASED IN CLAUSE
SQL> SELECT /*+RULE */ *
2 FROM My_Objects Obj
3 WHERE Obj.Object_Name IN
4 (SELECT Blk.Object_Name FROM My_Blocked_Objects Blk)
5 ;

7600 Zeilen ausgewõhlt.

Ausf³hrungsplan
———————————————————-
Plan hash value: 2264125269

———————————————————-
| Id | Operation | Name |
———————————————————-
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| MY_OBJECTS |
| 2 | NESTED LOOPS | |
| 3 | VIEW | VW_NSO_1 |
| 4 | SORT UNIQUE | |
| 5 | TABLE ACCESS FULL | MY_BLOCKED_OBJECTS |
|* 6 | INDEX RANGE SCAN | MY_OBJ_IDX |
———————————————————-

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

6 – access(“OBJ”.”OBJECT_NAME”=”$nso_col_1″)

Note
—–
– rule based optimizer used (consider using cbo)

Statistiken
———————————————————-
1 recursive calls
0 db block gets
15505 consistent gets
0 physical reads
0 redo size
104294 bytes sent via SQL*Net to client
5950 bytes received via SQL*Net from client
508 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
7600 rows processed

SQL>

The explain plan is expected RBO behaiver . it must use the SUB-Query as DRIVING QUERY. with very bad results :

IN Operator – RBO : 15505 consistent gets
IN Operator – CBO : 1352 consistent gets

Greeting
Karl

PS.: the IN Operator – CBO Trace output (number expected rows was different from lasst posting)…

SQL>
SQL> — IN CLAUSE
SQL> SELECT *
2 FROM My_Objects Obj
3 WHERE Obj.Object_Name IN
4 (SELECT Blk.Object_Name FROM My_Blocked_Objects Blk)
5 ;

7600 Zeilen ausgewõhlt.

Ausf³hrungsplan
———————————————————-
Plan hash value: 3465247318

————————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
————————————————————————————
| 0 | SELECT STATEMENT | | 8000 | 750K| 373 (4)| 00:00:05 |
|* 1 | HASH JOIN SEMI | | 8000 | 750K| 373 (4)| 00:00:05 |
| 2 | TABLE ACCESS FULL | MY_OBJECTS | 8000 | 562K| 27 (0)| 00:00:01 |
| 3 | INDEX FAST FULL SCAN| MY_BLK_IDX | 251K| 5900K| 340 (2)| 00:00:05 |
————————————————————————————

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

1 – access(“OBJ”.”OBJECT_NAME”=”BLK”.”OBJECT_NAME”)

Statistiken
———————————————————-
1 recursive calls
0 db block gets
1352 consistent gets
0 physical reads
0 redo size
104294 bytes sent via SQL*Net to client
5950 bytes received via SQL*Net from client
508 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
7600 rows processed

]]>
By: karl https://technology.amis.nl/2006/05/24/in-or-exist-or-doesnt-it-matter/#comment-3317 Thu, 25 May 2006 12:55:57 +0000 http://technology.amis.nl/blog/?p=1210#comment-3317 Hi Anton,
made it with a little bit more data and more columns – the results are the same on Oracle XE :

set timing off
set autotrace off
set echo on
DROP TABLE my_blocked_objects;
DROP TABLE my_objects;
create table my_blocked_objects AS SELECT do.owner || ‘.’ || do.object_name AS object_name , do.subobject_name, do.object_id, do.object_type, do.created, do.last_ddl_time, do.timestamp FROM dba_objects do, User_Objects uo;

create table my_objects AS SELECT do.owner || ‘.’ || do.object_name AS object_name , do.subobject_name, do.object_id, do.object_type, do.created, do.last_ddl_time, do.timestamp FROM dba_objects do , User_Objects uo1, User_Objects uo2 WHERE do.owner = USER;

create index my_blk_idx on my_blocked_objects(object_name)
/

create index my_obj_idx on my_objects(object_name)
/

begin
dbms_stats.gather_table_stats(user,’MY_BLOCKED_OBJECTS’);
dbms_stats.gather_table_stats(user,’MY_OBJECTS’);
end;
/

SQL> set line 120
SQL> select *
2 from my_objects obj
3 where obj.object_name in (select blk.object_name
4 from my_blocked_objects blk);

2548 Zeilen ausgewõhlt.

Ausf³hrungsplan
———————————————————-
Plan hash value: 3465247318

————————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
————————————————————————————
| 0 | SELECT STATEMENT | | 2744 | 246K| 374 (4)| 00:00:05 |
|* 1 | HASH JOIN SEMI | | 2744 | 246K| 374 (4)| 00:00:05 |
| 2 | TABLE ACCESS FULL | MY_OBJECTS | 2744 | 182K| 11 (0)| 00:00:01 |
| 3 | INDEX FAST FULL SCAN| MY_BLK_IDX | 264K| 6196K| 358 (2)| 00:00:05 |
————————————————————————————

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

1 – access(“OBJ”.”OBJECT_NAME”=”BLK”.”OBJECT_NAME”)

Statistiken
———————————————————-
0 recursive calls
0 db block gets
1349 consistent gets
0 physical reads
0 redo size
35871 bytes sent via SQL*Net to client
2243 bytes received via SQL*Net from client
171 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2548 rows processed

SQL> select *
2 from my_objects obj
3 where exists (select ”
4 from my_blocked_objects blk
5 where blk.object_name = obj.object_name)
6 /

2548 Zeilen ausgewõhlt.

Ausf³hrungsplan
———————————————————-
Plan hash value: 3465247318

————————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
————————————————————————————
| 0 | SELECT STATEMENT | | 2744 | 246K| 374 (4)| 00:00:05 |
|* 1 | HASH JOIN SEMI | | 2744 | 246K| 374 (4)| 00:00:05 |
| 2 | TABLE ACCESS FULL | MY_OBJECTS | 2744 | 182K| 11 (0)| 00:00:01 |
| 3 | INDEX FAST FULL SCAN| MY_BLK_IDX | 264K| 6196K| 358 (2)| 00:00:05 |
————————————————————————————

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

1 – access(“BLK”.”OBJECT_NAME”=”OBJ”.”OBJECT_NAME”)

Statistiken
———————————————————-
1 recursive calls
0 db block gets
1349 consistent gets
0 physical reads
0 redo size
35871 bytes sent via SQL*Net to client
2243 bytes received via SQL*Net from client
171 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2548 rows processed

SQL>

The intersting ist that the access predicates are the sam (join)

1 – access(“BLK”.”OBJECT_NAME”=”OBJ”.”OBJECT_NAME”)

So the optimizer seem not to see the *exists* construct or *in* construct but joins both tables.
Very interesting
Greetings
karl

]]>
By: Marco Gralike https://technology.amis.nl/2006/05/24/in-or-exist-or-doesnt-it-matter/#comment-3316 Wed, 24 May 2006 21:02:15 +0000 http://technology.amis.nl/blog/?p=1210#comment-3316 Also the “optimizer_max_permutations” should have been set to 2000 (instead of 80000). This is a known “feature” and should be corrected (probably also an off day of the Oracle employer who introduced this high value).

]]>