我有一个包含3亿条记录的表(表A),我想根据某些标准进行数据保留活动。所以我想删除该表的大约200M记录。
关于性能,我计划使用Table-A中最早的10M记录创建一个新表(表B)。然后我可以从Table-B中选择符合条件的记录,并在表A中删除它。
从表A中提取10M记录并使用SQL Loader加载到表B中需要大约5个小时。
我已经创建了索引,并且在适用的地方使用了parallel 32。
我想知道的是,
DBMS:Oracle 10g,PL / SQL和Shell。
感谢。
答案 0 :(得分:2)
如果要删除表中70%的记录,最好的方法是创建一个包含剩余30%行的新表,删除旧表并将新表重命名为旧桌子。创建新表的一种可能性是create-table-as-select语句(CTAS),但是也有可能使对运行系统的影响小得多,例如:可以使用物化视图来选择剩余数据并将物化视图转换为表格。该方法的细节取决于要求。 这种读取和写入比删除旧表的行更有效。
如果删除旧表的行,则可能需要重新组织旧表,这也将最终写入剩余的30%的数据。
答案 1 :(得分:0)
最好使用rowid但内联游标可以帮助你 在表中插入一个值(从表B中选择*,其中=条件)然后截断表A
答案 2 :(得分:0)
有没有更好的方法从Table-A中提取并加载它?您可以使用并行CTAS - 创建table-b作为select-table-a。您可以一步使用压缩和并行查询。
表-B。有没有更好的方法,除了创建临时
表(表-B)?更好的方法是分区表
答案 3 :(得分:0)
根据您的标准对表格进行分区可能是一种选择。
考虑一个标准是月份的情况。所有1月份的数据都属于Jan分区。所有2月份的数据都属于2月份的分区...
然后,当需要删除所有旧的1月数据时,您只需删除分区。
答案 4 :(得分:0)
我在搜索条件中使用的列上缺少一个索引。 除此之外,引用表上也缺少一些索引。
除了这个@miracle173答案也不错,但我们也有一些外键,如果我们使用这种方法可能会产生问题。
+1 to @miracle173
答案 5 :(得分:-1)
可能更好的方法是分区表A,但如果没有,你可以尝试快速和简单:
declare
i pls_integer :=0 ;
begin
for r in
( -- select what you want to move to second table
SELECT
rowid as rid,
col1,
col2,
col3
FROM
table_a t
WHERE
t.col < SYSDATE - 30 --- or other criteria
)
loop
insert /*+ append */ into table_b values (r.col1, r.col2, r.col3 ); -- insert it to second table
delete from table_a where rowid = r.rid; -- and delete it
if i < 500 -- check your best commit interval
then
i:=i+1;
else
commit;
i:=0;
end if;
end loop;
commit;
end;
在上面的示例中,您将在小型500行交易中移动记录。你可以使用集合和批量插入来优化它,但我想保留简单的代码。