84

我有这样的声明超时:

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

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

DELETE FROM [table] WHERE [COL] IN ( '1' )

到目前为止,它是 22 分钟,并且还在继续。

该表有 260,000 行,有四列。

有谁知道为什么这会这么慢以及如何加快速度?我在 [COL] 上确实有一个非唯一的非聚集索引,我正在执行 WHERE。我正在使用 SQL Server 2008 R2

更新:我桌上没有触发器。

4

15 回答 15

98

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

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

因此,您的选择是找出阻塞并修复它,或者在它们不会干扰正常生产负载的非工作时间运行删除。您可以批量运行删除(如果您有触发器、级联删除或大量记录,则很有用)。您可以删除并重新创建索引(最好在下班时间也可以这样做)。

于 2012-06-05T17:09:32.913 回答
74
  1. 禁用约束

    ALTER TABLE [TableName] NOCHECK CONSTRAINT ALL;

  2. 禁用索引

    ALTER INDEX ALL ON [TableName] DISABLE;

  3. 重建索引

    ALTER INDEX ALL ON [TableName] REBUILD;

  4. 启用约束

    ALTER TABLE [TableName] CHECK CONSTRAINT ALL;

  5. 再次删除

于 2015-07-10T03:49:57.613 回答
26

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

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
于 2012-06-05T16:48:31.853 回答
5

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

delete from tablename where col1 = 'v1' 

即使没有匹配的记录,也需要 30 秒,但是

delete from tablename where col1 = 'rubbish'

瞬间跑了

跑步

update statistics tablename

解决了这个问题

于 2018-10-11T13:36:49.357 回答
4

Preventive Action

Check with the help of SQL Profiler for the root cause of this issue. There may be Triggers causing the delay in Execution. It can be anything. Don't forget to Select the Database Name and Object Name while Starting the Trace to exclude scanning unnecessary queries...

Database Name Filtering

Table/Stored Procedure/Trigger Name Filtering

Corrective Action

As you said your table contains 260,000 records...and IN Predicate contains six values. Now, each record is being search 260,000 times for each value in IN Predicate. Instead it should be the Inner Join like below...

Delete K From YourTable1 K
Inner Join YourTable2 T on T.id = K.id

Insert the IN Predicate values into a Temporary Table or Local Variable

于 2012-06-05T16:55:47.400 回答
3

If the table you are deleting from has BEFORE/AFTER DELETE triggers, something in there could be causing your delay.

Additionally, if you have foreign keys referencing that table, additional UPDATEs or DELETEs may be occurring.

于 2012-06-05T16:45:58.123 回答
3

其他表可能对您的 [表] 有 FK 约束。因此数据库需要检查这些表以保持引用完整性。即使您拥有与这些 FK 对应的所有需要​​的索引,也要检查它们的数量。

当 NHibernate 在相同的列上错误地创建重复的 FK时,我遇到了这种情况,但名称不同(SQL Server 允许这样做)。它大大减慢了 DELETE 语句的运行速度。

于 2015-12-07T09:06:41.830 回答
1

检查此删除语句的执行计划。看看是否使用了索引搜索。还有什么是col的数据类型?

如果您使用了错误的数据类型,请更改更新语句(例如从 '1' 到 1 或 N'1')。

如果使用索引扫描,请考虑使用一些查询提示..

于 2012-06-06T08:26:53.417 回答
0

[COL] 真的是一个包含数字的字符字段,还是您可以摆脱值周围的单引号?@Alex 是正确的,IN 比 = 慢,所以如果你能做到这一点,你会更好:

DELETE FROM [table] WHERE [COL] = '1'

但更好的是使用数字而不是字符串来查找行(sql 喜欢数字):

 DELETE FROM [table] WHERE [COL] = 1

也许尝试:

 DELETE FROM [table] WHERE CAST([COL] AS INT) = 1

无论哪种情况,请确保您在列 [COL] 上有一个索引以加快表扫描。

于 2012-06-05T17:59:04.803 回答
0

较旧的主题,但仍然相关。当索引变得碎片化到成为问题而不是帮助的程度时,就会出现另一个问题。在这种情况下,答案将是重建或删除并重新创建索引并再次发出删除语句。

于 2020-08-03T14:31:44.770 回答
0

我阅读了这篇文章,它对解决任何类型的不便非常有帮助

https://support.microsoft.com/en-us/kb/224453

这是一个 waitresource KEY: 16:72057595075231744 (ab74b4daaf17)

-- First SQL Provider to find the SPID (Session ID)

-- Second Identify problem, check Status, Open_tran, Lastwaittype, waittype, and waittime
-- iMPORTANT Waitresource select * from sys.sysprocesses where spid = 57

select * from sys.databases where database_id=16

-- with Waitresource check this to obtain object id 
select * from sys.partitions where hobt_id=72057595075231744

select * from sys.objects where object_id=2105058535
于 2015-10-22T20:27:40.490 回答
0

如果您要删除表中的所有记录而不是少数几个,那么删除并重新创建表可能会快得多。

于 2017-03-20T21:13:46.630 回答
0

作为上面Andomar 答案的扩展,我有一个场景,前 700,000,000 条记录(约 12 亿条)处理速度非常快,每秒处理 25,000 条记录的块(大约)。但是,然后它开始需要 15 分钟才能完成 25,000 个批次。我将块大小减少到 5,000 条记录,然后它又恢复了以前的速度。我不确定我达到了什么内部阈值,但解决方法是减少记录数量,进一步恢复速度。

于 2020-10-12T19:20:23.183 回答
0

在检查了一个 SSIS 包(由于 SQL Server 执行命令真的很慢),这是在我写这篇文章之前大约 5-4 年在我们的客户端中设置的,我发现有以下任务:1 ) 将 XML 文件中的数据插入到名为 [Importbarcdes] 的表中。

2)在另一个目标表上合并命令,使用上述表作为源。

3) "delete from [Importbarcodes]",清除SSIS包的任务读取XML文件后插入的行的表。

在快速检查表 ImportBarcodes 上只有 1 行的所有语句(SELECT、UPDATE、DELETE 等)后,执行大约需要 2 分钟。

扩展事件显示了很多 PAGEIOLATCH_EX 等待通知。

表中没有索引,也没有注册触发器。

仔细检查表的属性,在存储选项卡和一般部分下,数据空间字段显示在页面中分配的空间超过 6 GIGABYTES。

发生了什么:

在过去的 4 年中,该查询每天运行大部分时间,在表中插入和删除数据,将未使用的页面文件留在后面而没有释放它们。

因此,这是扩展事件会话捕获的等待事件和表上缓慢执行的命令的主要原因。

运行ALTER TABLE ImportBarcodes REBUILD修复了释放所有未使用空间的问题。TRUNCATE TABLE ImportBarcodes做了类似的事情,唯一的区别是删除所有页面文件和数据。

于 2019-07-26T12:59:01.470 回答
-10

打开 CMD 并运行此命令

NET STOP MSSQLSERVER
NET START MSSQLSERVER

这将重新启动 SQL Server 实例。尝试在您的删除命令后再次运行

我在批处理脚本中有这个命令,如果遇到这样的问题,我会不时运行它。正常的 PC 重启不会是一样的,所以如果你的 sql server 遇到一些问题,重启实例是最有效的方法。

于 2018-02-05T03:52:39.983 回答