1

我有一个 5 GB 的表,现在我试图删除如下:

delete  from tablename
where to_char(screatetime,'yyyy-mm-dd') <'2009-06-01' 

但它运行了很长时间,没有任何响应。同时,我试图检查是否有人在下面阻止:

select l1.sid, ' IS BLOCKING ', l2.sid
from v$lock l1, v$lock l2
where l1.block =1 and l2.request > 0
and l1.id1=l2.id1
and l1.id2=l2.id2

但我也没有发现任何阻塞。

我怎样才能毫无问题地删除这些大数据?

4

4 回答 4

1
于 2010-02-02T07:49:57.183 回答
1

如果 screatetime 上有索引,则您的查询可能没有使用它。更改您的语句,以便您的 where 子句可以使用索引。

delete from tablename where screatetime < to_date('2009-06-01','yyyy-mm-dd')
于 2010-02-02T07:52:47.810 回答
1

当您首先锁定表时,它运行得更快。还要按照 Rene 的建议更改 where 子句。

LOCK TABLE tablename IN EXCLUSIVE MODE;

DELETE FROM tablename
where screatetime < to_date('2009-06-01','yyyy-mm-dd');

编辑:如果表不能被锁定,因为它经常被访问,你可以选择意大利腊肠策略来删除这些行:

BEGIN
  LOOP
    DELETE FROM tablename
      WHERE screatetime < to_date('2009-06-01','yyyy-mm-dd')
        AND ROWNUM<=10000;
    EXIT WHEN SQL%ROWCOUNT=0;
    COMMIT;
  END LOOP;
END;

总的来说,这会比较慢,但它不会破坏您的回滚段,您可以在另一个会话中看到进度(即 tablename 中的行数下降)。如果你因为某种原因不得不杀死它,回滚不会永远持续下去,而且你还没有丢失到目前为止所做的所有工作。

于 2010-02-02T10:18:45.690 回答
1

5GB 不是表大小的有用度量。总行数很重要。您要删除的行数占事务总数的比例。行的平均长度很重要。

如果要删除的行的比例很小,那么在创建一个screatetime稍后将删除的索引时可能是值得的。这可能意味着您的整个操作需要更长的时间,但至关重要的是,它将减少您删除行所需的时间。

另一方面,如果您要删除大量行,您可能会发现最好

  1. 使用'create table t1_copy as select * from t1 where screatedate >= to_date('2009-06-01','yyyy-mm-dd')` 创建表的副本
  2. rename使用命令交换表。
  3. 对新的 T1 重新应用约束、索引。

要记住的另一件事是删除比其他事务消耗更多的UNDO,因为它们需要更多信息来回滚。因此,如果您的记录很长和/或很多,那么您的 DBA 可能需要检查 UNDO 表空间(或回滚段,如果您仍在使用它们)。

最后,您是否进行过任何调查以了解时间的实际去向?DELETE 语句只是另一个查询,可以使用常规的调优技巧来解决它们。

于 2010-02-02T10:31:04.433 回答