删除几个记录从多个分区在oracle

vxf3dgd4  于 2023-06-29  发布在  Oracle
关注(0)|答案(1)|浏览(100)

1.我有一个表t_orders包含40mn条记录。
1.该表每天在trans_dt上进行分区。
1.我想根据p_code='OTC'删除大约2500万条记录
1.我想用下面的方法,这似乎更快。有没有什么方法可以像下面这样基于多个分区进行删除?例如使用2分区(SYS_P20209,SYS_P20345)。在使用一个分区的情况下,它工作得很好。

ALTER SESSION ENABLE PARALLEL DML;
DELETE t_orders PARTITION(SYS_P20209,SYS_P20345) WHERE p_code = 'OTC';
COMMIT;

提前谢谢你,喀什

kmbjn2e3

kmbjn2e31#

你想删除4000万中的2500万,或者整个表的62%?你不想使用DELETE,因为撤销和重做的数量将是巨大的,如果它失败或你中止它,你可能会结束一个非常长的回滚时间。处理此问题的正确方法是重新创建段。您可以通过以下几种方式执行此操作:
1.使用CREATE TABLE AS SELECT(CTAS)创建一个新表,其中只包含要保留的数据。CTAS允许分区语法,因此您可以在创建表时对其进行分区,而不是预先创建表或稍后更改表。然后重命名旧表,将新表重命名为旧表,应用任何赠款、索引等。旧table上的东西你就完了。这是不使用脚本的最有效的方法。
1.使用CREATE TABLE AS SELECT创建一个临时表,其中只包含要保留的数据。截断主表,启用并行dml并将临时表中的append插入回主表。这具有移动数据两次的缺点,但避免了必须重新定义依赖对象/赠款等。
1.由于它是分区的,您可以通过分区编写PL/SQL循环(查询all_tab_partitions以获得分区名称),并使用扩展分区命名语法逐个CTAS每个分区到临时表,只移动您想要保留的数据。使用扩展分区语法时,一次只能处理一个分区。然后使用ALTER TABLE EXCHANGE PARTITION将旧分区与临时表交换。完成后重建索引。这与#1 plus一样高效,避免了必须重新应用赠款和重新定义索引等。但当然只对分区表起作用。
1.最后,如果你绝对必须做一个真实的的DELETE(同样,不推荐),这里有一些选择:
禁用索引和触发器。启用并行dml和 hint(如果没有提示,启用并行dml可能不会执行任何操作):DELETE /*+ parallel(16) */ FROM t_orders...。完成后,重建索引并重新启用触发器。
4 b.通过分区名编写PL/SQL循环,并使用扩展的分区命名语法执行#4a中提示的并行dml删除,但仅针对一个分区。提交每个循环迭代。这可确保所有并行线程按数据块范围均匀分布工作负载,而不是Oracle可能选择分区分布,因为分区分布可能存在偏差并导致并行化效率降低。它还保持回滚时间和空间需求的撤消下降到一个更合理的水平,因为你只做一个分区的时间。但是如果失败了,你需要知道你在哪里停止了,因为这是在提交的块中而不是在一个事务中执行操作。示例:

BEGIN
   EXECUTE IMMEDIATE 'ALTER SESSION ENABLE PARALLEL DML';

   FOR rec_part IN (SELECT partition_name
                      FROM user_tab_partitions
                     WHERE table_name = 'T_ORDERS'
                    ORDER BY partition_position)
   LOOP
     dbms_output.put_line('Working on '||rec_part.partition_name);

     EXECUTE IMMEDIATE 'DELETE /*+ parallel(16) */ FROM t_orders PARTITION ('||rec_part.partition_name||') WHERE p_code = ''OTC''';
     COMMIT;
   END LOOP;
 END;

相关问题