从空表中删除forver

Wil*_*ill 5 sql oracle performance plsql

我有一个以前有大量行的空表.

该表在其中许多列上有大约10列和索引,以及多列上的索引.

DELETE FROM item WHERE 1=1
Run Code Online (Sandbox Code Playgroud)

这大约需要40秒才能完成

SELECT * FROM item
Run Code Online (Sandbox Code Playgroud)

这需要4秒钟.

SELECT*FROM ITEM的执行计划显示如下:

SQL> select * from midas_item;

no rows selected

Elapsed: 00:00:04.29

Execution Plan
----------------------------------------------------------
 0      SELECT STATEMENT Optimizer=CHOOSE (Cost=19 Card=123 Bytes=73
      80)

1    0   TABLE ACCESS (FULL) OF 'MIDAS_ITEM' (Cost=19 Card=123 Byte
      s=7380)





Statistics
----------------------------------------------------------
      0  recursive calls
      0  db block gets
   5263  consistent gets
   5252  physical reads
      0  redo size
   1030  bytes sent via SQL*Net to client
    372  bytes received via SQL*Net from client
      1  SQL*Net roundtrips to/from client
      0  sorts (memory)
      0  sorts (disk)
      0  rows processed
Run Code Online (Sandbox Code Playgroud)

任何想法为什么这些将花费这么长时间,如何解决它将非常感谢!!

Gar*_*ers 5

一种可能性是锁。也就是说,表中有一行已被另一个删除提交并锁定。您的删除坐在并等待锁定。提交锁定事务后,您的删除就可以完成了。

第二种可能性是您首先运行了删除,它将块从磁盘提取到缓存中(这需要时间)。When the select ran, the data was in the cache and so ran quicker. 我认为这不太可能,因为您选择的统计数据表明“5252 物理读取”,因此它没有从 SGA 缓存中获取它们。不过,可能涉及磁盘缓存。

第三种可能性是有一个 BEFORE/AFTER DELETE 触发器(不是 FOR EACH ROW)做了一些事情。

第四种可能性是 DELETE 导致延迟块清除。当这些行被实际删除时,如果它们在提交之前被写入磁盘,它们仍然会有锁/事务信息。您的删除随之而来,读取块,查看现在过时的事务信息,将其删除并重新写入块。

第五种可能性是争用。也许在删除的同时发生了更多的事情。

很多可能性。如果您可以重现它,则使用等待事件进行跟踪并通过 TKPROF 运行它。


Cor*_*nga 2

select只是进行全表扫描。另一方面(在 Oracle 中)删除必须将整个删除的行存储在回滚段中,以便允许您稍后撤消更改(因此它甚至可能比插入慢)。

您可以在 Ask Tom 论坛上找到与此相关的非常长且有用的讨论。根据您的业务案例,也许您可​​以应用更多技术。

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2345591157689