从另一个(大)表更新大表的最快方法?

时间:2019-01-29 13:45:42

标签: sql oracle plsql

我在Oracle中有两个大表(每个表约4000万行)。 我需要基于单个联接使用tableB中的数据更新tableA。 我尝试过:

update tableA a
set (a.column2)=
(select b.column2 from tableB b
where a.column1=b.column1)

它可以工作,但是大约需要1个小时才能完成。

我还检查了以下内容(解释计划):

merge into tableA a
using (select b.column1, b.column2 from tableB b) b
on (a.column1=b.column1)
when matched then
update set a.column2=b.column2

但是它的成本似乎是第一个查询的10倍。 我也尝试使用游标进行更新,但花了2个小时才完成。

两个表的索引都在column1上。 TableA还按月划分分区。

任何想法如何以更有效的方式完成此过程?

谢谢!

3 个答案:

答案 0 :(得分:2)

我会尝试在第一个查询中添加where子句:

update tableA a
    set a.column2 = (select b.column2 from tableB b
where a.column1 = b.column1)
    where a.column2 <> (select b.column2 from tableB b
where a.column1 = b.column1);

(假设目标值不是NULL。)

答案 1 :(得分:2)

您是否尝试过以下方法?

UPDATE 
(SELECT tableA.column2 as OLD, tableB.column2 as NEW
 FROM tableA
 INNER JOIN tableB
 ON tableA.column1 = tableB.column1
) t
SET t.old = t.new

答案 2 :(得分:1)

对于批量插入或更新,我将永远在oracle中使用。 以下代码可能会有一些错误,但是您可以将其更正并用于批量处理

declare
c_limit number:10000;
CURSOR c_update IS
SELECT b.column1,b.column2 from tableB b,tableA a  where a.column1=b.column1
type upd_Arry is table of c_update%rowtype;
upd_val  upd_Arry;

BEGIN
    OPEN c_update;
    LOOP
    FETCH c_update BULK COLLECT INTO upd_val LIMIT c_limit;

    FORALL i IN 1..l_data.COUNT
    update tableA 
      set column2=upd_val(i).b.column2
      where column1=upd_val(i).b.column1;

    EXIT WHEN c_update%NOTFOUND;
    END LOOP;
    commit;
    CLOSE c_update;
END ;