【发布时间】:2016-01-19 04:26:26
【问题描述】:
我们为 Oracle DB 中的一个表(已经有 20 亿行)构建了一个删除查询。此查询作为 PL/SQL Proc 的一部分执行。以下是我们当前仍在测试中的查询。
DELETE from TABLE1
where ROWID IN (SELECT rid from (SELECT ROWID rid, ROW_NUMBER() over (PARTITION BY C1_Varchar2,C2_Varchar2 ORDER BY C3_Date desc) as Rank
from TABLE1 where C3_Date < ADD_MONTHS(SYSDATE, -20))
where Rank <> 1);
这个查询是删除所有从当月开始超过20个月的记录(来自TABLE1),除了由C1和C2列的唯一组合形成的最新记录。此查询将删除大约 12% 的记录。
当我们运行查询时,我们得到以下错误。
ORA-00604: 递归 SQL 级别 2 发生错误 ORA-04031: 无法分配 32 字节的共享内存 ("shared pool","select i.obj#,i.ts#,i.file#,...","SQLA","tmp")
请注意,该表是基于 C3_Date 列进行分区的。但是按照上述逻辑,我们仍然会在分区中保留很少的记录,因此不能选择删除整个分区。
谁能建议如何处理此删除以使其更高效和稳定?
计划如下:
Plan hash value: 2112788339
---------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 1 | 59 | | 9080K (2)| 30:16:07 | | |
| 1 | DELETE | TABLE1 | | | | | | | |
| 2 | NESTED LOOPS | | 1 | 59 | | 9080K (2)| 30:16:07 | | |
| 3 | VIEW | VW_NSO_1 | 496M| 5684M| | 6785K (1)| 22:37:12 | | |
| 4 | SORT UNIQUE | | 1 | 11G| | | | | |
|* 5 | VIEW | | 496M| 11G| | 6785K (1)| 22:37:12 | | |
| 6 | WINDOW SORT | | 496M| 20G| 26G| 6785K (1)| 22:37:12 | | |
|* 7 | INDEX SKIP SCAN | XPKTABLE1 | 496M| 20G| | 1206K (1)| 04:01:18 | | |
| 8 | TABLE ACCESS BY USER ROWID| TABLE1 | 1 | 47 | | 1 (0)| 00:00:01 | ROWID | ROWID |
---------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - filter("RANK"<>1)
7 - access("C3_Date"<ADD_MONTHS(SYSDATE@!,-15))
filter("C3_Date"<ADD_MONTHS(SYSDATE@!,-15))
【问题讨论】:
-
你能发布这个查询的解释计划吗?只需执行
EXPLAIN PLAN FOR DELETE from TABLE1 where .... .....,然后运行SELECT * FROM Table( DBMS_XPLAN.Display ),然后复制结果(作为文本),并将其粘贴到问题中。 -
4031 是一个异常错误,可能与查询优化无关。 4031 意味着严重的内存问题。这些问题可能是由其他进程引起的,而失败的查询并不是问题的真正原因。如果它只是一个测试数据库,而你认为这是侥幸,我就重新启动它。
标签: sql oracle oracle11g query-optimization sql-delete