oracle删除查询花费了太多时间

时间:2009-08-25 09:45:35

标签: sql oracle

我有一个像

这样的查询
DELETE from tablename where colname = value;

需要很长时间才能执行。 可能是什么原因?我有一个关于colname的索引。

7 个答案:

答案 0 :(得分:31)

对于您的查询需要很长时间的原因,可能有多种解释:

  1. 您可能被另一个会话阻止(最有可能)。在删除之前,您应确保没有其他人锁定行,例如:issue SELECT NULL FROM tablename WHERE colname=:value FOR UPDATE NOWAIT
  2. 可能有ON DELETE TRIGGER可以执行其他工作,
  3. 检查指向此表的UNINDEXED REFERENCE CONSTRAINTS(有script from AskTom可帮助您确定是否存在此类未编入索引的外键。)

答案 1 :(得分:5)

可能是您的表与多个表有很大的行数。

答案 2 :(得分:3)

该指数的选择性如何?如果你的表有一百万行,并且该值达到十五万,那么你的索引就没用了。事实上,如果实际使用它可能会比无用更糟糕。请记住,DELETE类似于SELECT语句:我们可以调整其访问路径。

此外,删除会占用大量的撤消表空间,因此如果系统使用频繁,您可能会遇到争用。在多用户系统中,另一个会话可能会锁定您要删除的行。

你有ON DELETE触发器吗?你有ON DELETE CASCADE外键约束吗?

编辑:鉴于您所说的一切,特别是有问题的列是主键,因此您尝试删除单行,如果花费很长时间则更有可能某些其他进程或用户对该行有锁定。是否有任何内容显示在V$LOCK

答案 3 :(得分:0)

您的表格是否包含更多记录?
是否有一些在数据库服务器上运行的递归程序(一些嵌套循环等)? 如果数据库服务器在不同的机器上,请检查网络问

答案 4 :(得分:0)

如果某些事情变得缓慢,而你不知道为什么,请追踪它并找出答案。

How do I troubleshoot performance problems with an Oracle SQL statement

答案 5 :(得分:0)

所以我只是发表我的经验。可能对某人有帮助。

查询

delete from foo
where foo_id not in ( 
  select max(foo_id) from foo group by foo_bar_id, foo_qux_id
);

花了16秒。从表foo中删除总计2300条记录中的1700条记录。

我按照其他答案的指示检查了外键上的所有索引。这没有用。

<强>解决方案:

将查询更改为

delete from foo
where foo_id in ( 
  select foo_id from foo
  minus
  select max(foo_id) from foo group by foo_bar_id, foo_qux_id
);

我已将not in更改为in并使用minus来获得正确的结果。

现在查询在0.04秒内执行。

答案 6 :(得分:0)

Oracle和mysql之间存在显着差异:

Oracle不会自动为外键创建索引,而mysql会自动创建。然后,如果您有一些父表可以在其上执行delete命令,则必须在子表的外键上创建索引,否则如果子表有很多行,则在父表上的delete命令将非常非常慢,因为它必须浏览子表的所有记录每个删除任何父记录。

然后要从Oracle数据库的父表中删除时要小心。