我正在尝试使用分别具有2亿条记录和3000万条记录的REF_TAB表从表TAB1更新一列CODE,但是更新记录需要3-4个小时。
TAB1 -- 200000000(200mn)
ID VARCHAR2(10) PK on ID
T_ID VARCHAR2(10) --- duplicate values
X_CD VARCHAR2(2)
CODE VARCHAR2(2) -- list partition with 30 codes
REF_TAB --30000000(30 mn)
T_ID VARCHAR2(10) --- unique values
CODE VARCHAR2(2)
TAB1.ID主键上的唯一索引是唯一索引。
我尝试过MERGE。还有其他方法可以提高查询性能或通过其他任何方式?
MERGE /*+ parallel(A,4) append */ INTO TAB1 A
USING (SELECT T_ID,CODE FROM REF_TAB) R
ON ( A.T_ID = R.T_ID
AND A.X_CD IS NOT NULL
)
WHEN MATCHED THEN
UPDATE
SET A.CODE = R.CODE;
COMMIT;
with append
Plan hash value: 3594611329
--------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | MERGE STATEMENT | | 93M| 714M| 494K (4)| 00:00:03 | | | | | |
| 1 | MERGE | TAB1 | | | | | | | | | |
| 2 | PX COORDINATOR | | | | | | | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10001 | 93M| 27G| 494K (4)| 00:00:03 | | | Q1,01 | P->S | QC (RAND) |
| 4 | VIEW | | | | | | | | Q1,01 | PCWP | |
|* 5 | HASH JOIN | | 93M| 27G| 494K (4)| 00:00:03 | | | Q1,01 | PCWP | |
| 6 | PX RECEIVE | | 32M| 374M| 8430 (5)| 00:00:01 | | | Q1,01 | PCWP | |
| 7 | PX SEND BROADCAST | :TQ10000 | 32M| 374M| 8430 (5)| 00:00:01 | | | Q1,00 | S->P | BROADCAST |
| 8 | PX SELECTOR | | | | | | | | Q1,00 | SCWC | |
| 9 | TABLE ACCESS FULL| REF_TAB | 32M| 374M| 8430 (5)| 00:00:01 | | | Q1,00 | SCWP | |
| 10 | PX BLOCK ITERATOR | | 93M| 26G| 484K (3)| 00:00:03 | 1 | 35 | Q1,01 | PCWC | |
|* 11 | TABLE ACCESS FULL | TAB1 | 93M| 26G| 484K (3)| 00:00:03 | 1 | 35 | Q1,01 | PCWP | |
--------------------------------------------------------------------------------------------------------------------------------------------------
without append
Plan hash value: 3594611329
--------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | MERGE STATEMENT | | 103M| 790M| 494K (4)| 00:00:03 | | | | | |
| 1 | MERGE | TAB1 | | | | | | | | | |
| 2 | PX COORDINATOR | | | | | | | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10001 | 103M| 30G| 494K (4)| 00:00:03 | | | Q1,01 | P->S | QC (RAND) |
| 4 | VIEW | | | | | | | | Q1,01 | PCWP | |
|* 5 | HASH JOIN | | 103M| 30G| 494K (4)| 00:00:03 | | | Q1,01 | PCWP | |
| 6 | PX RECEIVE | | 32M| 374M| 8430 (5)| 00:00:01 | | | Q1,01 | PCWP | |
| 7 | PX SEND BROADCAST | :TQ10000 | 32M| 374M| 8430 (5)| 00:00:01 | | | Q1,00 | S->P | BROADCAST |
| 8 | PX SELECTOR | | | | | | | | Q1,00 | SCWC | |
| 9 | TABLE ACCESS FULL| REF_TAB | 32M| 374M| 8430 (5)| 00:00:01 | | | Q1,00 | SCWP | |
| 10 | PX BLOCK ITERATOR | | 103M| 29G| 485K (4)| 00:00:03 | 1 | 35 | Q1,01 | PCWC | |
|* 11 | TABLE ACCESS FULL | TAB1 | 103M| 29G| 485K (4)| 00:00:03 | 1 | 35 | Q1,01 | PCWP | |
--------------------------------------------------------------------------------------------------------------------------------------------------
1)添加索引
您可以在表T_ID
的tab1
列上添加索引。那应该大大加快声明的速度。或者,如果您将T_ID
中的REF_TAB
设为主键也应该有所帮助,那么这可能是唯一的。
在两种情况下,您都应该摆脱一次全表扫描,并用索引或索引范围扫描代替它,这应该更快。
2)创建表格解决方案
另一个应该更快的解决方案是创建一个新表tab2
:
create table tab2 as
SELECT t.ID
, T_ID
, t.X_CD
, r.CODE
FROM tab1 t
JOIN ref_tab r USING(T_ID)
将索引,授予,约束添加到tab2,删除tab1,然后将tab2重命名为tab1。这样,您就不会存储回滚信息,回滚信息是进行批量更新时的主要资源问题。
3)使用外键+联接代替重复数据(数据库规范化)
您可能还考虑在tab1
上添加外键:
ALTER TABLE tab1
ADD CONSTRAINT tab1_fk FOREIGN KEY (T_ID)
REFERENCES REF_TAB (T_ID)
然后从tab1删除CODE
列并读取每个JOIN
的值-因此,更改后不必更新该值。