当执行这个简单的SQL Delete语句时,我从SQL Server获得超时:
DELETE FROM dbo.[User] WHERE Id = 95146
表中大约有95000条记录。
我认为这可能是因为表上的索引,所以我删除了除了主键(Id)之外的所有索引,但这并没有帮助。
我也删除了我创建的所有统计数据,但也没有任何影响。
我还能做些什么来优化这个?
亲切的问候,大卫。
您有多少个外键引用Users
的Id
列,这些列上有索引吗?
如果cascade设置为NO_ACTION
,正如您所指出的,时间可能会被SQL Server花费,必须对这些表中的每个表执行全表扫描,以确保没有对Id
95146的引用-我以前看到过,如果其他表很大,这一次很容易花费几分钟。
这太奇怪了。我的猜测是,您有一个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时超时。这是一个包含几个连接的删除操作,其中一个连接涉及的表非常大。奇怪的是,如果我将相同的join/where子句的delete转换为SELECT *
,那么查询将立即完成,并且有零结果(即delete语句显然正在进行一些长时间的大表扫描,但实际上没有找到任何要删除的内容)。
最后的帮助是,我在Show实际执行计划打开的情况下运行它的select语句版本,这有一个建议的非唯一索引要添加到其中一个表中。在我添加了这个索引之后,select语句仍然立即运行,但是现在delete语句也运行了!
在语句运行时,查看系统取出的正在运行的任务和锁的列表。您可以从Activity Monitor中获得此信息,或者您可以在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