I proved myself wrong :-)
drop table t
/
drop table s
/
create table t as select mod(level,1000000) t_val from dual connect by level <= 10000000
/
exec dbms_stats.gather_table_stats('sysadm','t')
create table s as select 'A' as s_fld, t_val as s_old_val, 1000000-t_val as s_new_val from (select distinct t_val from t)
/
create index s_idx on s(s_fld,s_old_val)
/
exec dbms_stats.gather_table_stats('sysadm','s')
update t
set t_val = (select s_new_val
from s
where s_fld = 'A'
and s_old_val = t_val)
where exists(select null
from s
where s_fld = 'A'
and s_old_val = t_val)
/
Rows Execution Plan
------- ---------------------------------------------------
0 UPDATE STATEMENT GOAL: ALL_ROWS
0 UPDATE OF 'T'
0 HASH JOIN (RIGHT SEMI)
0 TABLE ACCESS GOAL: ANALYZED (FULL) OF 'S' (TABLE)
0 TABLE ACCESS GOAL: ANALYZED (FULL) OF 'T' (TABLE)
0 TABLE ACCESS GOAL: ANALYZED (BY INDEX ROWID) OF 'S' (TABLE)
0 INDEX GOAL: ANALYZED (RANGE SCAN) OF 'S_IDX' (INDEX)
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.06 0.14 0 0 0 0
Execute 1 405.31 694.99 13024 30016193 10223745 10000000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 405.37 695.14 13024 30016193 10223745 10000000
update t
set t_val = (select s_new_val
from s
where s_fld = 'A'
and s_old_val = t_val)
where exists(select null
from s
where s_fld = 'A'
and s_old_val = t_val
and rownum < 2)
/
Rows Execution Plan
------- ---------------------------------------------------
0 UPDATE STATEMENT GOAL: ALL_ROWS
0 UPDATE OF 'T'
0 FILTER
0 TABLE ACCESS GOAL: ANALYZED (FULL) OF 'T' (TABLE)
0 COUNT (STOPKEY)
0 INDEX GOAL: ANALYZED (RANGE SCAN) OF 'S_IDX' (INDEX)
0 TABLE ACCESS GOAL: ANALYZED (BY INDEX ROWID) OF 'S' (TABLE)
0 INDEX GOAL: ANALYZED (RANGE SCAN) OF 'S_IDX' (INDEX)
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.06 0.14 0 0 0 0
Execute 1 912.43 1390.87 127033 100664115 10551252 10000000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 912.50 1391.02 127033 100664115 10551252 10000000
As you have already said Hash join gives better perfomance when doing update of large amount of data. And full scan is better than Index scan for such cases.
Thank you.