违反Oracle唯一约束

问题描述 投票:1回答:1

我有一个表,记录超过3000万。在进行插入时,我需要避免违反Unique约束。

当我使用这种NOT EXIST方法时,插入将永远花费。实际上,它在运行24小时后无法完成。而且我不能使用ignore_row_on_dupkey_index提示,因为此表具有1个以上的PK列。

另一个选择是插入子集。但是我想知道在进行子设置之前是否还有其他方法。

insert into tlb1 a
select * from tlb2 b
where not exists (select 'x' from tlb1 c
                  where b.pk = c.pk)
oracle unique-constraint
1个回答
0
投票

[重要决定取决于插入的numbe rof行,即表TBL2中的行数

如果此数字相当低(例如成百上千,那么您可以安全地使用您的方法,只要PK列上有一个索引-应该用斜线强制实施唯一约束。

请检查使用的执行计划是否与下面的类似

-------------------------------------------------------------------------------------
| Id  | Operation                | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT         |          |   110 |  2860 |   113   (0)| 00:00:02 |
|   1 |  LOAD TABLE CONVENTIONAL | TBL1     |       |       |            |          |
|   2 |   NESTED LOOPS ANTI      |          |   110 |  2860 |   113   (0)| 00:00:02 |
|   3 |    TABLE ACCESS FULL     | TBL2     |   110 |  1430 |     3   (0)| 00:00:01 |
|*  4 |    INDEX UNIQUE SCAN     | TBL1_IXD |     1 |    13 |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("B"."PK"="C"."PK")

[C0意味着对于每个插入的行,将执行单个索引查找,以检查目标表中是否已存在该键。

这对于插入的行数较少时效果很好。对于较大的插入(数百万行),优化器将切换到NESTED LOOPS ANTI,即来自两个表的所有行将被合并以得到可能的重复项。

这可能会花费一些时间(但通常不会是24小时),并且使用HASH JOIN RIGHT ANTI的方法消除了加入的需要。

DML Error Logging

这种方法将很好地扩展,特别是当重复项的数量比插入的行数少时。它与普通插入物相当:

INSERT INTO tbl1 (pk)
SELECT pk
FROM   tbl3
LOG ERRORS INTO err$_tbl1 ('dedup tbl3') REJECT LIMIT UNLIMITED;
© www.soinside.com 2019 - 2024. All rights reserved.