【问题标题】:Delete from empty table taking forver从空表中删除需要永远
【发布时间】:2011-01-30 12:21:36
【问题描述】:

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

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

DELETE FROM item WHERE 1=1

这大约需要 40 秒才能完成

SELECT * FROM item

这需要 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

任何想法为什么这些会花费这么长时间以及如何解决它将不胜感激!

【问题讨论】:

  • 你能告诉我这张表有多少数据(行)吗?
  • 是否还有其他空表通过外键引用该表?
  • 我上次清理时,该表大约有 200k 行。虽然它比过去有更多的东西(在它的生命周期中可能有 200 万个差异行)
  • 您已经给出了 SELECT 的计划和统计信息,但 DELETE 呢?

标签: sql performance oracle plsql


【解决方案1】:

如果表上有很多索引,那么删除将需要时间,因为索引中的每个条目也需要删除。索引加快读取过程并减慢写入或其他修改过程(因此是快速选择)。

-- 编辑:抱歉没有完整阅读问题。如果表为空,则不能是索引问题。否则我会感到惊讶——

【讨论】:

  • 好吧,选择本身也需要 4 秒,但是是的,相比之下更快
  • 但是他说表已经没有行了,所以 DELETE 不应该修改索引。
【解决方案2】:

如果您定期从表中删除所有行,“截断表 XXX”通常比批量删除快得多。也许试试看,看看你能多快得到它。

【讨论】:

  • 正确 -- 但请确保您了解 TRUNCATE 的作用(释放空间、提交事务)。
  • 我确实使用 truncate 删除了所有行
【解决方案3】:

如果您的表以前填充了大量数据,那么 Oracle 将扫描它直到高水位线,即使它现在没有数据。您可以使用 TRUNCATE 语句来重置 HWM。

Also on AskTom

【讨论】:

  • 这也是我的第一个想法——但我不确定它是否解释了为什么 DELETE 比 SELECT 慢得多。
  • 我原来是用TRUNCATE TABLE来清除内容的,用了之后还是很慢。
【解决方案4】:

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

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

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

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

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

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

【讨论】:

    【解决方案5】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-08
      • 2021-12-08
      • 2022-10-06
      • 2019-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多