问题描述
我在这里寻找专家建议。我们处于这样一种情况,我们正在从父表中删除数据,该表没有关联的子记录,但在父表和子表之间启用了RI。子表是巨大的,它有超过十亿个记录。虽然作为删除的一部分的父记录没有子记录,但删除需要很长时间 (超过20小时,但仍在运行)。我们正在寻找替代方法来实现这一目标。
选项 #1: 在启用RI约束时删除父级 (需要20多个小时,但仍在运行)
选项2: 我们正在研究禁用RI约束并从父表中删除分区,并最终启用RI约束。但是我们不确定使能约束对十亿行表需要多长时间,以及这是否真的比选项 #1更好。
选项 #3: 在快照之前恢复数据库。
你能告诉我哪些选择更好吗?还是其他更好的选择?
感谢您的回复。
选项 #1: 在启用RI约束时删除父级 (需要20多个小时,但仍在运行)
选项2: 我们正在研究禁用RI约束并从父表中删除分区,并最终启用RI约束。但是我们不确定使能约束对十亿行表需要多长时间,以及这是否真的比选项 #1更好。
选项 #3: 在快照之前恢复数据库。
你能告诉我哪些选择更好吗?还是其他更好的选择?
感谢您的回复。
专家解答
第一个问题:
您真的,真的确定这是因为FK而缓慢吗?父表上没有触发器?没有其他可能阻止删除的DML?
第二个问题:
您是否在FK列的子表上有索引?
如果答案为 “否”,则Oracle数据库将对子表进行完整扫描for each row您从父级删除。
这里有一个小例子。从T2 -> t1有一个未索引的FK。T2中没有行。从T1删除删除两行:
一旦你用tkprof或类似的方法格式化了跟踪文件,你会看到类似的东西:
请注意,“执行” 调用的计数为2。父级的每行一次。在t2 (x) 上创建索引可以避免子级的全扫描。
如果以上都没有帮助,并且您仍然想尝试禁用该约束,请记住,在delete运行时,您的数据不受保护。所以理论上你应该在停电时这样做...
您可以使用novalidate选项加快启用约束的速度。这不会检查现有行是否满足约束,因此将比常规启用快得多。虽然这确实给你留下了不可靠的数据的机会。特别是如果您决定在应用程序仍在运行时冒险禁用FK!
您真的,真的确定这是因为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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。