暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 禁用RI约束以加速删除

askTom 2017-05-03
295

问题描述

我在这里寻找专家建议。我们处于这样一种情况,我们正在从父表中删除数据,该表没有关联的子记录,但在父表和子表之间启用了RI。子表是巨大的,它有超过十亿个记录。虽然作为删除的一部分的父记录没有子记录,但删除需要很长时间 (超过20小时,但仍在运行)。我们正在寻找替代方法来实现这一目标。

选项 #1: 在启用RI约束时删除父级 (需要20多个小时,但仍在运行)
选项2: 我们正在研究禁用RI约束并从父表中删除分区,并最终启用RI约束。但是我们不确定使能约束对十亿行表需要多长时间,以及这是否真的比选项 #1更好。

选项 #3: 在快照之前恢复数据库。


你能告诉我哪些选择更好吗?还是其他更好的选择?

感谢您的回复。

专家解答

第一个问题:

您真的,真的确定这是因为FK而缓慢吗?父表上没有触发器?没有其他可能阻止删除的DML?

第二个问题:

您是否在FK列的子表上有索引?

如果答案为 “否”,则Oracle数据库将对子表进行完整扫描for each row您从父级删除。

这里有一个小例子。从T2 -> t1有一个未索引的FK。T2中没有行。从T1删除删除两行:

create table t1 (
  x int primary key
);

create table t2 (
  x int references t1 (x)
);

insert into t1 values (1);
insert into t1 values (2);
commit;

alter session set tracefile_identifier = chris;
exec dbms_monitor.session_trace_enable();
delete t1;
exit


一旦你用tkprof或类似的方法格式化了跟踪文件,你会看到类似的东西:

select /*+ all_rows */ count(1)
from
 "CHRIS"."T2" where "X" = :1


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      2      0.00       0.00          0          0          0           0
Fetch        2      0.00       0.00          0          0          0           2
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        5      0.00       0.00          0          0          0           2

Misses in library cache during parse: 1
Misses in library cache during execute: 1
Optimizer mode: ALL_ROWS
Parsing user id: SYS   (recursive depth: 1)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  SORT AGGREGATE (cr=0 pr=0 pw=0 time=14 us)
         0          0          0   TABLE ACCESS FULL T2 (cr=0 pr=0 pw=0 time=4 us cost=2 size=13 card=1)


请注意,“执行” 调用的计数为2。父级的每行一次。在t2 (x) 上创建索引可以避免子级的全扫描。

如果以上都没有帮助,并且您仍然想尝试禁用该约束,请记住,在delete运行时,您的数据不受保护。所以理论上你应该在停电时这样做...

您可以使用novalidate选项加快启用约束的速度。这不会检查现有行是否满足约束,因此将比常规启用快得多。虽然这确实给你留下了不可靠的数据的机会。特别是如果您决定在应用程序仍在运行时冒险禁用FK!
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论