SQL中的删除语句非常慢
我有这样的说法是超时的:
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
更新:我没有触发器在桌子上。
可能导致删除速度变慢的原因是:
- 删除了很多logging
- 许多指标
- 子表中的外键缺less索引。 (感谢@CesarAlvaradoDiaz在评论中提到这一点)
- 僵局和阻塞
- 触发器
- 级联删除(您正在删除的那十条父logging可能意味着数百万条儿童logging被删除)
- 事务日志需要增长
- 许多外键检查
因此,您的select是找出什么是阻塞的,并在不影响正常生产负载的情况下,在非工作时间运行删除操作。 您可以批量运行删除(如果有触发器,级联删除或大量logging,则可以使用该删除)。 您可以删除并重新创build索引(如果您也可以在非工作时间内完成索引,则最好)。
-
禁用CONSTRAINT
ALTER TABLE [TableName] NOCHECK CONSTRAINT ALL;
-
禁用索引
ALTER INDEX ALL ON [TableName] DISABLE;
-
重build索引
ALTER INDEX ALL ON [TableName] REBUILD;
-
启用CONSTRAINT
ALTER TABLE [TableName] CHECK CONSTRAINT ALL;
-
再次删除
删除很多行可能会非常缓慢。 尝试一次删除几个,如:
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
预防措施
在SQL Profiler
的帮助下查看此问题的根本原因。 可能有Triggers
导致延迟执行。 它可以是任何东西。 不要忘记在启动Trace
时selectDatabase Name
和Object Name
以排除扫描不必要的查询…
数据库名称过滤
表/存储过程/触发器名称过滤
纠正措施
正如你所说,你的表格包含26万条logging…而“ IN Predicate
包含六个值。 现在,每个logging在IN Predicate
每个值中search260000次。 相反,它应该是下面的Inner Join …
Delete K From YourTable1 K Inner Join YourTable2 T on T.id = K.id
将IN Predicate
值插入Temporary Table
或Local Variable
如果您从中删除的表具有BEFORE / AFTER DELETE触发器,则可能会导致延迟。
此外,如果您有引用该表的外键,可能会发生其他UPDATE或DELETE。
其他表可能会对你的[table]有FK约束。 所以DB需要检查这些表以保持参照完整性。 即使你有所有需要的指标对应这些FKs,检查他们的金额。
当NHibernate在相同的列上错误地创build了重复的FK时 ,却遇到了不同的名称(这是SQL Server允许的)。 它大大减缓了DELETE语句的运行速度。
[COL]是一个真正的数字字段,还是可以摆脱值的单引号? @Alex是正确的,IN比=慢,所以如果你能做到这一点,你会更好:
DELETE FROM [table] WHERE [COL] = '1'
但更好的是使用数字而不是string来查找行(SQL喜欢数字):
DELETE FROM [table] WHERE [COL] = 1
也许尝试:
DELETE FROM [table] WHERE CAST([COL] AS INT) = 1
无论哪种情况,请确保在[COL]列上有一个索引来加速表扫描。
检查此删除语句的执行计划。 看看索引查找是否被使用。 col的数据types是什么?
如果您使用错误的数据types,更改更新语句(如从'1'到1或N'1')。
如果使用索引扫描,请考虑使用一些查询提示 。
我阅读这篇文章对解决各种不便之处非常有帮助
https://support.microsoft.com/en-us/kb/224453
这是一个等待资源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
如果删除表中的所有logging,而不是select几个logging,则删除并重新创build表可能会快得多。