Quantcast
Channel: Mohamed Houri’s Oracle Notes
Viewing all articles
Browse latest Browse all 224

Intelligent CBO

$
0
0

Just a small note to show you a situation I’ve recently encountered which shows how the CBO is intelligent. I have the following two pieces of SQL

UPDATE t1 a
SET
a.padding = 'yyyyyyyy'
WHERE
a.id1 in
(SELECT
     b.id2
FROM t2  b
WHERE a.id1 = a.n1   ---> spot this
);

And the second one

UPDATE t1 a
SET
a.padding = 'yyyyyyyy'
WHERE
a.id1 in
(SELECT
 b.id2
 FROM t2  b
)
AND a.id1 = a.n1;       ---> spot this

I would not have written the first SQL in order to restrict the updates only to records in t1 having identical id1 and n1. I would have logically issued the second one instead.

But to my surprise the CBO recognized that the where clause in the subquery (WHERE a.id1 = a.n1 ) should be applied to the main update by replacing it with the AND clause outside the brackets. Here below are the corresponding execution plans

First query

Plan hash value: 1788758844
----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | UPDATE STATEMENT    |      |     1 |    91 |   899   (2)| 00:00:03 |
|   1 |  UPDATE             | T1   |       |       |            |          |
|*  2 |   HASH JOIN SEMI    |      |     1 |    91 |   899   (2)| 00:00:03 |
|*  3 |    TABLE ACCESS FULL| T1   |     1 |    78 |   447   (2)| 00:00:02 |
|   4 |    TABLE ACCESS FULL| T2   |   104K|  1320K|   449   (1)| 00:00:02 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("A"."ID1"="B"."ID2")
3 - filter("A"."ID1"="A"."N1")

Note
-----
- dynamic sampling used for this statement (level=2)

Second query

Plan hash value: 1788758844
----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | UPDATE STATEMENT    |      |     1 |    91 |   899   (2)| 00:00:03 |
|   1 |  UPDATE             | T1   |       |       |            |          |
|*  2 |   HASH JOIN SEMI    |      |     1 |    91 |   899   (2)| 00:00:03 |
|*  3 |    TABLE ACCESS FULL| T1   |     1 |    78 |   447   (2)| 00:00:02 |
|   4 |    TABLE ACCESS FULL| T2   |   104K|  1320K|   449   (1)| 00:00:02 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("A"."ID1"="B"."ID2")
3 - filter("A"."ID1"="A"."N1")

Note
-----
- dynamic sampling used for this statement (level=2)

The same plan hash value and the same predicate part. It’s funny enough.

If you want to play with the test here is the model (borrowed from Jonathan Lewis)

create table t1
as
with generator as (
select  --+ materialize
rownum id
from dual
connect by
level <= 10000)
select
   rownum id1,
   trunc(dbms_random.value(1,1000))    n1,
   lpad(rownum,10,'0') small_vc,
   rpad('x',100)       padding
from
 generator   v1,
 generator   v2
where
rownum <= 100000;
create table t2
 as
with generator as (
select  --+ materialize
rownum id
from dual
connect by
level <= 10000)

select
 rownum                  id2,
 trunc(dbms_random.value(10001,20001))   x1,
 lpad(rownum,10,'0') small_vc,
rpad('x',100)       padding
from
 generator   v1,
 generator   v2
where
rownum <= 100000;


Viewing all articles
Browse latest Browse all 224

Trending Articles