You Asked
Hi Tom!
I've a big table "x" which has columns: id, month, quantity_ordered, quantity_received.
The table contains about 2,00,000 records.
There is another big table "y" which has the same number of records as "x", with the columns: id, month, quantity.
What I want to do is update table x, set quantity_ordered and quantity_received equal to quantity of table y where x.id = y.id and x.month = y.month.
The simple query I wrote is :
UPDATE x tab1
SET tab1.quantity_ordered = (
SELECT tab2.quantity
FROM y tab2
WHERE tab2.id = tab1.id
AND tab2.month = tab1.month
);
COMMIT;
The above query updates only the quantity_ordered column from "x". It does the required activity, but it takes lot of time, i.e., over 45 min. Also I didn't try updating the second column, i.e., quantity_received from "x", since updating 2,00,000 records for only one column takes lot of time.
Whereas, if I try to do the same thing by clubbing records of each month into a separate table, say y_01, y_02, etc., then things are better.
For eg.,
UPDATE x tab1
SET tab1.quantity_ordered = (
SELECT tab2.quantity
FROM y_01 tab2
WHERE tab2.id = tab1.id
AND tab2.month = tab1.month
)
WHERE tab1.month = '01';
COMMIT;
This above query does it quite fast, say about 5 min.
Can you please tell me as to how to update both quantity_ordered and quantity_received columns both in one shot while the update is really fast?
Thanks & Regards
-Rahul.
and Tom said...
Update a join....
ops$tkyte@ORA9IR2> create table x ( id number, month number, quantity_ordered number, quantity_received number );
Table created.
Elapsed: 00:00:00.02
ops$tkyte@ORA9IR2> insert /*+ APPEND */ into x
2 select id, mod(id,12)+1, object_id, data_object_id
3 from big_table.big_table;
1000000 rows created.
Elapsed: 00:00:02.28
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> create table y ( id number , month number, quantity_ordered number, quantity_received number, primary key(id,month) );
Table created.
Elapsed: 00:00:00.03
ops$tkyte@ORA9IR2> insert /*+ APPEND */ into y
2 select id, mod(id,12)+1, rownum, object_id
3 from big_table.big_table;
1000000 rows created.
Elapsed: 00:00:40.50
ops$tkyte@ORA9IR2> commit;
Commit complete.
Elapsed: 00:00:00.02
ops$tkyte@ORA9IR2> exec dbms_stats.gather_table_stats( user, 'X' );
PL/SQL procedure successfully completed.
Elapsed: 00:00:08.39
ops$tkyte@ORA9IR2> exec dbms_stats.gather_table_stats( user, 'Y', cascade=>true );
PL/SQL procedure successfully completed.
Elapsed: 00:00:15.78
ops$tkyte@ORA9IR2> set timing on
ops$tkyte@ORA9IR2> set autotrace on explain
ops$tkyte@ORA9IR2> update (select x.quantity_ordered xqo,
2 x.quantity_received xqr,
3 y.quantity_ordered yqo,
4 y.quantity_received yqr
5 from x, y
6 where x.id = y.id
7 and x.month = y.month )
8 set xqo = yqo, xqr = yqr;
1000000 rows updated.
Elapsed: 00:02:31.42
Execution Plan
----------------------------------------------------------
0
UPDATE STATEMENT Optimizer=CHOOSE (Cost=2282 Card=1000000 Bytes=30000000)
1 0
UPDATE OF 'X'
2 1
HASH JOIN (Cost=2282 Card=1000000 Bytes=30000000)
3 2
TABLE ACCESS (FULL) OF 'X' (Cost=386 Card=1000000 Bytes=13000000)
4 2
TABLE ACCESS (FULL) OF 'Y' (Cost=486 Card=1000000 Bytes=17000000)
And if a single index is actually used during the update - that is a problem, we want two full scans and a hash join!
Rating
(4 ratings)
Is this answer out of date? If it is, please let us know via a Comment