我有一个类似的应用程序:
delete from tableA where columnA='somevalue' and rownum<1000
在周期中:
while(deletedRows>0) {
begin tran
deletedRows = session ... "delete from tableA where columnA='somevalue'
and rownum<1000"....
commit tran
}
它运行几次(每次删除需要近20秒)并且在挂了很长时间之后 为什么?有可能解决吗? 感谢。
删除在循环而不是单个SQL语句中运行的原因是缺少回滚空间。有关详细信息,请参阅this question。
答案 0 :(得分:1)
每次查询从头开始扫描表。因此,它会扫描没有要删除的行的区域(columnA='somevalue'
)。他们越来越远离桌子的第一个街区。
如果表格很大且没有columnA='somevalue'
,则查询会花时间验证您所有情况的行。
您可以做的是在columnA
上制作索引。在这种情况下,引擎将知道更快,具有该条件的行在哪里(搜索索引的指数时间更快)。
另一种可能性,如果你在一个concurent系统中,有人更新了你试图删除的行,但没有提交事务,所以该行被锁定。
答案 1 :(得分:1)
你可能遇到很多不同的问题。正如您所说数据库挂起的主要原因是您的数据库正在点击 ORA-00257存档错误。
每次删除都会生成一个重做向量,然后将所有重做下载到存档日志中。当存档日志空间被耗尽时,会话会挂起并保持卡住,直到有人释放空间。 通常,您的DBA有一个每小时运行一次归档日志备份的作业(这可能是几个小时,或者每5分钟,具体取决于数据库工作负载等等),并且在备份完成后,所有会话都会正确进行。
根据数据库配置的不同,从客户端的角度来看,您可能看不到错误,只是描述了会话等待的行为,直到释放空间为止。
在设计方面,我同意其他用户认为循环中的DELETE并不是一个好主意。知道为什么要尝试执行此循环而不是单个DELETE语句可能会很有趣。