繁体   English   中英

从匹配案例的另一个表值更新 Oracle 表

[英]Update Oracle table from another table value on matching case

我有一个主表(比如 tableA,其中包含 tab_a_id、field_code、field_id 列)。 还有另一个表,比如 tableB,它有列 area_id、area_code。 tab_a_id 是 TableA 的主键。 我想根据 field_code 更新 tableA 的 field_id。 tableA 的 field_code 和 tableB 的 area_code 匹配但不相同,意味着 field_code 有其他与 area_code 列不匹配的值。 我想设置 field_id = area_id if field_code = area_code 但是,如果不匹配,它应该设置为默认值 -1,即“未知”字段。 我尝试使用子查询和批量更新(例如 Update tableA SET field_id = (SELECT area_code from tableB where area_code = field_code))。 这适用于有限的数据集。 但我有 300 万条匹配记录,这意味着 300 万条子查询。 另一个问题是有 700 万条记录,导致 400 万条不匹配的记录和无用的子查询。 是否有任何最佳方法可以以最少的时间和更高的效率更新此类记录。 我尝试了合并命令,但与 forall 循环查询相比,它的性能很差

更新 700 万行中的 3 行似乎是这里的问题。

我在小型机器上的数据库中创建了一个测试集,获得结果的最快方法是创建一个包含所需数据和稍后交换名称的新表 (CTAS)。 我没有使用主键列 tab_a_id 来简化答案。

CREATE TABLE a (field_id NUMBER, field_code VARCHAR2(30)) NOLOGGING;

CREATE TABLE b (area_id NUMBER, area_code VARCHAR2(30)) NOLOGGING;

使用MERGEUPDATE非常慢(15 分钟),大概是因为更改量很大:

UPDATE a SET field_id=-1 WHERE field_code NOT IN (SELECT area_code FROM b);
5,599,989 rows updated. (560 seconds)

MERGE INTO a USING b ON (a.field_code=b.area_code)
 WHEN MATCHED THEN UPDATE SET a.field_id = b.area_id;
2,400,011 rows merged. (232 seconds)

但是,使用更改的数据创建新表要快 20 倍,并且只需要 38 秒:

CREATE TABLE x NOLOGGING AS 
SELECT a.field_id, NVL(b.area_code, -1) AS field_code
  FROM a JOIN b ON a.field_code=b.area_code;

这是测试数据的生成:

INSERT /*+ APPEND */ INTO a (field_id, field_code) SELECT id, to_char(id) from (select level as id from dual connect by rownum <= 1000000); COMMIT;
INSERT /*+ APPEND */ INTO a (field_id, field_code) SELECT field_id+1000000, to_char(field_id+1000000) from a; COMMIT;
INSERT /*+ APPEND */ INTO a (field_id, field_code) SELECT field_id+2000000, to_char(field_id+2000000) from a; COMMIT;
INSERT /*+ APPEND */ INTO a (field_id, field_code) SELECT field_id+4000000, to_char(field_id+4000000) from a; COMMIT;
EXEC dbms_stats.gather_table_stats(null, 'a');

INSERT /*+ APPEND */ INTO b (area_id, area_code) SELECT -field_id, field_code FROM a SAMPLE (30);
exec dbms_stats.gather_table_stats(null, 'b');

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM