SQL中的Delete语句非常慢

Kyl*_*yle 68 sql sql-server sql-server-2008 database-optimization

我有这样的陈述超时:

DELETE FROM [table] WHERE [COL] IN ( '1', '2', '6', '12', '24', '7', '3', '5')
Run Code Online (Sandbox Code Playgroud)

我试着像这样一次做一个:

DELETE FROM [table] WHERE [COL] IN ( '1' )
Run Code Online (Sandbox Code Playgroud)

到目前为止,它已经到了22分钟仍在继续.

该表中有260,000行,是四列.

有没有人有任何想法为什么这会如此缓慢以及如何加快它?我确实在[COL]上有一个非唯一的非聚集索引,我在做WHERE.我正在使用SQL Server 2008 R2

更新:我没有触发器.

HLG*_*GEM 79

可能导致删除速度缓慢的事情:

  • 删除大量记录
  • 很多指数
  • 子表中的外键上缺少索引.(感谢@CesarAlvaradoDiaz在评论中提到这一点)
  • 死锁和阻塞
  • 触发器
  • 级联删除(您删除的那10个父记录可能意味着数百万个子记录被删除)
  • 需要增长的事务日志
  • 许多外键检查

所以你的选择是找出什么是阻塞并修复它或在非工作时间运行删除,因为它们不会干扰正常的生产负载.您可以批量运行删除(如果您有触发器,级联删除或大量记录,则非常有用).您可以删除并重新创建索引(如果您也可以在非工作时间执行此操作,则最好).

  • 我有一个案例,当我试图从包含约100万行的表中删除但它花了很长时间.使用`select*`查询行很快,但删除速度非常慢.然后我意识到另一个有20亿(!)行的表有一个外键.当然,FK列没有编入索引.解决方案:删除FK,删除行,重新创建FK.重新创建FK仍然需要一些时间,但速度要快得多. (20认同)
  • 重要提示:如果您有外键,那么表中的这些应该被编入索引 (3认同)

Sha*_*b J 56

  1. 禁用CONSTRAINT

    ALTER TABLE [TableName] NOCHECK CONSTRAINT ALL;

  2. 禁用索引

    ALTER INDEX ALL ON [TableName] DISABLE;

  3. 重建指数

    ALTER INDEX ALL ON [TableName] REBUILD;

  4. 启用CONSTRAINT

    ALTER TABLE [TableName] CHECK CONSTRAINT ALL;

  5. 再次删除

  • 这有效,但解释会很好. (13认同)
  • 一个缺点是在`alter index all on mytable disable`之后,大多数查询都停止工作."查询处理器无法生成计划".一旦索引重建并重新启用约束,它们似乎再次起作用. (2认同)
  • 警告:重建BIG表(超过200万个)中的索引需要花费大量时间(小时...)。就我而言,最好像@Andomar的回答中那样做。 (2认同)
  • 使用此功能时要非常非常小心,在此之后,所有具有该表外键的表都将其外键关闭!!!!!!!!! 您必须再次为每个表手动打开它们 (2认同)

And*_*mar 20

删除大量行可能非常慢.尝试一次删除一些,例如:

delete top (10) YourTable where col in ('1','2','3','4')
while @@rowcount > 0
    begin
    delete top (10) YourTable where col in ('1','2','3','4')
    end
Run Code Online (Sandbox Code Playgroud)

  • 这确实有效!我唯一的解释是它不需要写很大的日志。如果您还有其他解释,请与我分享。 (2认同)

小智 9

就我而言,数据库统计数据已损坏。该声明

delete from tablename where col1 = 'v1' 
Run Code Online (Sandbox Code Playgroud)

即使没有匹配的记录,也花费了 30 秒,但是

delete from tablename where col1 = 'rubbish'
Run Code Online (Sandbox Code Playgroud)

立即跑

跑步

update statistics tablename
Run Code Online (Sandbox Code Playgroud)

解决了问题


小智 5

预防措施

在 的帮助下检查SQL Profiler此问题的根本原因。可能会Triggers导致执行延迟。它可以是任何东西。不要忘记在启动时选择Database Name和来排除扫描不必要的查询...Object NameTrace

数据库名称过滤

表/存储过程/触发器名称过滤

纠正措施

正如您所说,您的表包含 260,000 条记录......并且IN Predicate包含六个值。现在,针对 中的每个值,每条记录都会被搜索 260,000 次IN Predicate。相反,它应该是像下面这样的内部连接......

Delete K From YourTable1 K
Inner Join YourTable2 T on T.id = K.id
Run Code Online (Sandbox Code Playgroud)

IN Predicate值插入Temporary TableLocal Variable