Search code examples
sqloracle-databasecorrelated-subquery

Oracle SQL correlated update low performance


I have to update table(table3) with data from two other tables. These two tables (table1,table2) are both describing single object, therefore table1.id equals table2.id for that single object. Table 3 is a many-to-many mapping table for that object and another one which is not important here. Into that mapping table I need to put some data from table1 and table2.

I am trying to update table3 with correlated query, but it takes a very long time to complete. I ran this query on group of ~500.000 records and it runs for over an hour now.

Am I doing something wrong here?

UPDATE table3 t3
SET (t3.some_value1, t3.other_value1, t3.some_value2, t3.other_value2) =
(   SELECT t1.some_value1, t1.other_value1, t2.some_value2, t2.other_value2
    FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id
    WHERE t3.fk = t1.id)
WHERE EXISTS (SELECT 1 FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id WHERE t3.fk = t1.id);


SELECT * FROM table3;

SQL Fiddle


Solution

  • Use this:

    UPDATE
          (SELECT
                T3.SOME_VALUE1 TARGET1,
                T3.OTHER_VALUE1 TARGET2,
                T3.SOME_VALUE2 TARGET3,
                T3.OTHER_VALUE2 TARGET4,
                T1.SOME_VALUE1 SOURCE1,
                T1.OTHER_VALUE1 SOURCE2,
                T2.SOME_VALUE2 SOURCE3,
                T2.OTHER_VALUE2 SOURCE4
           FROM
                TABLE1 T1
                JOIN TABLE2 T2
                    ON T1.ID = T2.ID
                JOIN T3
                    ON T3.FK = T1.ID)
    SET
          TARGET1   = SOURCE1,
          TARGET2   = SOURCE2,
          TARGET3   = SOURCE3,
          TARGET4   = SOURCE4;
    

    If you face ORA-01779 cannot modify a column which maps to a non key-preserved table then try using UPDATE /*+ BYPASS_UJCV */ or add a unique index on T1.ID, T2.ID, T3.FK