从包含数万亿条记录的 Oracle 表中删除数十亿条记录
Posted
技术标签:
【中文标题】从包含数万亿条记录的 Oracle 表中删除数十亿条记录【英文标题】:Deleting billions of records from Oracle Table containing trillions of records 【发布时间】:2021-02-26 18:17:58 【问题描述】:我需要删除大约。来自具有大约 100 + 十亿行的 Oracle 表的 300 亿行。我有我需要在临时表中删除的行的所有 ID。目前我正在使用如下的单个删除语句,也使用 SUBPARTITION 并在 temp_table 上创建索引。然而,这需要 4 个多小时才能在 PRODUCTION 中完成。
DELETE FROM table_name SUBPARTITION(subpartition_name) WHERE id IN (SELECT id FROM temp_table);
COMMIT;
有没有办法可以优化它以使其运行得更快。
仅供参考:
-
我所指的 oracle 表对于多个客户端来说是通用的,所以下面的选项在这里不适合。
创建新表并将所需数据移入其中并删除旧表,然后将新表重命名为旧表。
批量删除:循环遍历临时表并删除如下所示的内容,在非生产环境中需要更多时间,并且不确定它在生产环境中的情况。
DECLARE
vCT NUMBER(38) := 0;
BEGIN
FOR t IN (SELECT id FROM temp_table) LOOP
DELETE FROM table_name WHERE id = t.id;
......
......
COMMIT;
END IF;
END LOOP;
COMMIT;
END;
-
在这里创建单独的 DELETE 语句的选项也不可行,因为记录数以十亿为单位。
我确实检查了,我正在使用它的表上有分区和子分区,并且没有没有子表依赖它。
请提出建议。
【问题讨论】:
您如何确定将哪些id
值放入临时表中?如果这是需要定期发生的事情,通常会设计该表,以便您可以只删除一个或多个分区,而不是删除 300 亿行。
似乎是您的分区键设计不佳。通常,您删除或截断整个(子)分区。
@JustinCave - 我查询到原始表,并根据一些条件确定需要删除哪些记录。因此将所有 id 捕获到临时表中,这样我就不必一次又一次地运行相同的条件。现在 temp_table 具有所有要从原始表中删除的 ID。
@WernfriedDomscheit - 设计确实很差,但必须忍受。
但是这些条件和分区方案有关系吗?还是您真的要从每个分区中删除 30% 的数据?
【参考方案1】:
删除(或更新)大量行是痛苦并且需要很多时间。
管理它最有效的方法是使用updatable join views
请求但应该没问题的是 delta 表上的一个唯一索引,其中包含要删除的 id
。
在使用这种方法时,请确保大表在id
列上没有唯一索引。 如果两个表在连接列上都有唯一索引,则会出现一些技术问题 - 见下文。
比使用以下查询(如果您想明智地使用子分区)删除
delete from
(
select delta.id, big.id big_id
from delta
join big subpartition (SYS_SUBP220880)
on delta.id = big.id
)
Oracle 使用两个表的 hash join,在您的情况下,这是管理您的规模的唯一可能性。您可以部署并行选项,不要忘记启用它。
这是预期的执行计划:
-------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 100K| 1757K| 875 (2)| 00:00:01 | | |
| 1 | DELETE | BIG | | | | | | |
|* 2 | HASH JOIN | | 100K| 1757K| 875 (2)| 00:00:01 | | |
| 3 | TABLE ACCESS FULL | DELTA | 100K| 488K| 47 (3)| 00:00:01 | | |
| 4 | PARTITION COMBINED ITERATOR| | 783K| 9947K| 825 (1)| 00:00:01 | KEY | KEY |
| 5 | TABLE ACCESS FULL | BIG | 783K| 9947K| 825 (1)| 00:00:01 | 65 | 65 |
-------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DELTA"."ID"="BIG"."ID")
注意 - 如果多个连接表被保留,请参阅文档Note on Updatable Views
对于 DELETE 语句,如果连接导致多个保留键的表,则 Oracle 数据库将从 FROM 子句中命名的第一个表中删除,无论视图是否创建为 WITH CHECK OPTION。
【讨论】:
以上是关于从包含数万亿条记录的 Oracle 表中删除数十亿条记录的主要内容,如果未能解决你的问题,请参考以下文章
将 s3 中跨 CSV 文件的数十亿条记录推送到 MongoDb
如何使用mongo在sinatra的handsontable中轻松加载数十亿条记录?