删除操作间歇性减慢 oracle 11g
Delete Operation Slows down intermittently oracle 11g
我们在生产环境中进行了审计 Table,我们每天在 PL/SQL 批次中删除近 1500 万条数据(超过几天的数据)。如果情况良好,此查询需要 1.5 小时才能删除相同的数据。但是有时候,即使在 4 小时内,这也不会间歇性地删除相同数量的数据。此 table 上没有触发器,已为创建的列编制索引。
DELETE FROM SIEBEL.CX_AUDIT_SEARCH
WHERE CREATED < '20-MAy-2020' AND rownum <= 10000;
解释 pla:
DELETE STATEMENT ALL_ROWS 6 10000 180000
DELETE SIEBEL.CX_AUDIT_SEARCH
COUNT(STOPKEY) ROWNUM<=10000
INDEX(RANGE SCAN) SIEBEL.CX_AUDIT_SEARCH_U1 ANALYZED 6 170692 3072456 "CREATED"<'20-MAy-2020'
能否请您提出任何可能的原因。
评论有点长
对于此过程,您想要分区 table。这会将每个分区的 table 存储在单独的 "files" 中。并且可以删除分区——这个过程比删除行要快得多。
您已将要删除的行描述为早于特定日期的行。这是分区解决方案的最佳点。
您可以在 documentation 中了解更多信息。我很惊讶您可以拥有如此大的数据库而不知道此功能。
很明显这是一个很忙的table。 15M rows/day 表示大约 10416 rows/minute,这意味着在您删除这些行时,正在插入数千条记录。当 Oracle 尝试删除旧行并更新 CREATED 索引时,将插入并提交更多行。
我看到您正在尝试一次删除 10000 行。我假设你在这 10000 行之后提交,所以下面的方法可能会更快一些,因为 SELECT 只是 运行 一次而且你不会重新扫描 1500 次繁忙的 table.. .
declare
cursor c_rowids is
SELECT T.ROWID
FROM SIEBEL.CX_AUDIT_SEARCH T
WHERE CREATED < '20-MAy-2020';
type t_tbl_rowids is table of rowid;
tbl_rowids t_tbl_rowids;
begin
open c_rowids;
Loop
fetch c_rowids bulk collect into tbl_rowids limit 10000;
exit when tbl_rowids.count = 0;
forall i in 1..tbl_rowids.count
DELETE FROM SIEBEL.CX_AUDIT_SEARCH
WHERE ROWID = tbl_rowids(i);
COMMIT;
End loop;
close c_rowids;
end;
我们在生产环境中进行了审计 Table,我们每天在 PL/SQL 批次中删除近 1500 万条数据(超过几天的数据)。如果情况良好,此查询需要 1.5 小时才能删除相同的数据。但是有时候,即使在 4 小时内,这也不会间歇性地删除相同数量的数据。此 table 上没有触发器,已为创建的列编制索引。
DELETE FROM SIEBEL.CX_AUDIT_SEARCH
WHERE CREATED < '20-MAy-2020' AND rownum <= 10000;
解释 pla:
DELETE STATEMENT ALL_ROWS 6 10000 180000
DELETE SIEBEL.CX_AUDIT_SEARCH
COUNT(STOPKEY) ROWNUM<=10000
INDEX(RANGE SCAN) SIEBEL.CX_AUDIT_SEARCH_U1 ANALYZED 6 170692 3072456 "CREATED"<'20-MAy-2020'
能否请您提出任何可能的原因。
评论有点长
对于此过程,您想要分区 table。这会将每个分区的 table 存储在单独的 "files" 中。并且可以删除分区——这个过程比删除行要快得多。
您已将要删除的行描述为早于特定日期的行。这是分区解决方案的最佳点。
您可以在 documentation 中了解更多信息。我很惊讶您可以拥有如此大的数据库而不知道此功能。
很明显这是一个很忙的table。 15M rows/day 表示大约 10416 rows/minute,这意味着在您删除这些行时,正在插入数千条记录。当 Oracle 尝试删除旧行并更新 CREATED 索引时,将插入并提交更多行。
我看到您正在尝试一次删除 10000 行。我假设你在这 10000 行之后提交,所以下面的方法可能会更快一些,因为 SELECT 只是 运行 一次而且你不会重新扫描 1500 次繁忙的 table.. .
declare
cursor c_rowids is
SELECT T.ROWID
FROM SIEBEL.CX_AUDIT_SEARCH T
WHERE CREATED < '20-MAy-2020';
type t_tbl_rowids is table of rowid;
tbl_rowids t_tbl_rowids;
begin
open c_rowids;
Loop
fetch c_rowids bulk collect into tbl_rowids limit 10000;
exit when tbl_rowids.count = 0;
forall i in 1..tbl_rowids.count
DELETE FROM SIEBEL.CX_AUDIT_SEARCH
WHERE ROWID = tbl_rowids(i);
COMMIT;
End loop;
close c_rowids;
end;