我有以下 SQL 查询,它在 avg 上运行。40 秒,需要一些指导,我可以在哪里改进或重写:
Declare @status_D INT,
Declare @StatusIP INT,
Declare @Status_F INT,
SELECT @status_D = Id From Batchtablestatus (NOLOCK) Where desc ='Value1';
SELECT @StatusIP = Id From Batchtablestatus (NOLOCK) Where desc ='Value2';
SELECT @Status_F = Id From Batchtablestatus (NOLOCK) Where desc ='Value3'
BEGIN TRAN
UPdate U
SET
U.[id]= @StatusIP,
U.[EnabledDate]= Getdate()
OUTPUT deleted.col1,
deleted.col2,
deleted.col3,
deleted.col4,
Inserted.id
FROM (
SELECT TOP 5000 * FROM BatchChangeTable WITH (ROWLOCK,UPDLOCK)
WHERE [id] IN ( @status_D ,Status_F)
ORDER BY [ModifiedTime] )U;
COMMIT TRAN
我收到来自 blitzcache 的警告,因为强制序列化、昂贵的排序、不可分割和合并加入 "Mant to Many" = True
我们唯一的索引是在 id 上,它是一个以 id 作为前导键列的 NC 索引。
如果可以的话,我会尝试更新我的问题,如果执行计划。截至目前,SELECT 中的表约为 1 亿。在 col1 上也有 PK/CI。
我已经问过用户为什么我们在那个拉近 50 多列但在更新中使用较少的 TOP 中做 *,可能 bi 想错了,但我想到了。
将索引添加到修改时间似乎也无济于事。
请建议还有什么可以检查的。谢谢
警告
OUTPUT
(没有目标或@table
变量会导致这种情况,但不是#temp
表)ModifiedTime
没有支持索引和查询模式的情况下进行排序如何修复它
您需要一个良好的支持索引:
但是查询的编写方式
IN
将被解释为范围谓词,并且ORDER BY ModifiedDate
可能仍会导致排序操作。为了充分利用索引,您需要更改表单以使用两个相等谓词和 a 。UNION ALL
您还需要重写查询以使用动态 SQL,以免受到局部变量的副作用的影响。
成品将如下所示:
您需要稍微调整一下以适应您的实际情况,但它应该让您朝着正确的方向前进。
基于可用信息的想法:
代码: