执行这个简单的 SQL 删除语句时,我从 SQL Server 得到超时:
DELETE FROM dbo.[User] WHERE Id = 95146
表中约有 95.000 条记录。
我认为这可能是因为表上的索引,所以我删除了除了聚集的主键(Id)之外的所有内容,但这没有帮助。
我也删除了我创建的所有统计数据,但也没有任何效果。
我还能做些什么来优化这一点?
亲切的问候, 大卫
您有多少个外键引用
Id
的 Users
列,这些列上有索引吗?
如果级联设置为
NO_ACTION
,正如您所指出的,SQL Server 可能需要对每个表执行全表扫描以确保没有引用 Id
95146 - I如果其他桌子很大,以前就见过这很容易一次花费几分钟。
这很奇怪。我的猜测是您有一个 ON DELETE CASCADE 外键引用架构中其他位置的 Users 表。检查你的限制:
SELECT f.name AS ForeignKey,
OBJECT_NAME(f.parent_object_id) AS TableName,
COL_NAME(fc.parent_object_id,fc.parent_column_id) AS ColumnName,
OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
COL_NAME(fc.referenced_object_id,
fc.referenced_column_id) AS ReferenceColumnName,
f.delete_referential_action_desc
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id
我正在努力解决一个
DELETE
语句,该语句导致我们的 ERP (Epicor 10) 系统在夜间运行 MRP 时超时。这是一个带有一些连接的删除,并且连接涉及的其中一个表相当大。奇怪的是,如果我将删除转换为 SELECT *
对于相同的连接/where 子句,那么查询将立即完成,并且结果为零(即删除语句显然正在执行一些长而大的表扫描,但它实际上没有找到任何要删除的内容)。
最终有帮助的是,我在打开 显示实际执行计划的情况下运行了它的 select 语句版本,并且有一个建议的非唯一索引添加到其中一个表中。添加此索引后,select 语句仍然立即运行,但现在删除语句也运行了!
当语句运行时,查看正在运行的任务列表以及系统取出的锁。您可以从活动监视器获取此信息,也可以在视图
sys.dm_os_waiting_tasks
中查看正在运行的任务,并使用 exec sp_lock
和 sys.dm_tran_locks
锁定。
另外,在 SQL Server Management Studio 中,输入此语句并查看估计的执行计划。也许您将能够看到 SQL Server 正在尝试做什么。
看一下该表的外键。您可能需要在其他表上添加一些索引来优化外键断言。
除了其他响应之外,也许您的 DELETE 被其他一些活动阻止(查看 sp_who2 的 BlkBy 列中是否有您 spid 的任何值),或者表上可能有一个触发器正在执行不正常的操作。提到的大多数事情都会减慢删除速度,但除非在极其复杂的情况下,否则不足以导致超时。
我的超时是由于未完成的事务引起的。我开始于
BEGIN TRAN
但没有执行
COMMIT TRAN
或
ROLLBACK TRAN
我也遇到了同样的问题。
我的表(300k 行)无法包含主键和原始数据。
从[表]删除总是超时。 即使更新单行(由 ID(不唯一)和另一个字段标识)也会随机超时。
解决方案:更改一个字段,并将其设置为索引(在我的例子中为ID)。 PS:索引与主键不同。