我有一个像
这样的查询DELETE from tablename where colname = value;
需要很长时间才能执行。 可能是什么原因?我有一个关于colname的索引。
答案 0 :(得分:31)
对于您的查询需要很长时间的原因,可能有多种解释:
SELECT NULL FROM tablename WHERE colname=:value FOR UPDATE NOWAIT
,ON DELETE TRIGGER
可以执行其他工作,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数据库的父表中删除时要小心。