SQL Server 2012,Amazon RDS
这是我的简单查询
update [dbo].[DeliveryPlan]
set [Amount] = dp.Amount +
case when @useAmountColumn = 1 and dbo.ConvertToInt(bs.Amount) > 0
then dbo.ConvertToInt(bs.Amount)
else @amount
end
from
BaseSpecification bs
join
BaseSpecificationStatusType t on (StatusTypeID = t.StatusTypeID)
join
[DeliveryPlan] dp on (dp.BaseSpecificationID = bs.BaseSpecificationID and dp.ItemID = @itemID)
where
bs.BaseID = 130 and t.IsActive = 1
它无法完成。如果条件bs.BaseID = 130(更新7000行)更改为bs.BaseID = 3(更新1000000行),则持续13秒。
统计是实际的,我认为
在性能监视器中,我看到5%的处理器使用率
当我使用sp观察活动连接和此查询时 tempdb_allocations是32,tembdb_current - 32,读取 - 32 000 000,cpu - 860 000(查询持续20分钟)
有什么问题?
更新:我为[DeliveryPlan]
添加了非聚集索引 - BaseSpecificationID + ItemID
,问题就消失了。不幸的是,我每天都会遇到不同的问题。而且问题不可预测地消失了。
答案 0 :(得分:0)
您的基表可能会遇到锁定状态。
优化您的查询以直接更新dp
,以避免更新DeliveryPlan
的所有行
update dp set [Amount] = dp.Amount +
case
when @useAmountColumn=1 and dbo.ConvertToInt(bs.Amount)>0 then
dbo.ConvertToInt(bs.Amount)
else @amount
end
from
BaseSpecification bs
join BaseSpecificationStatusType t on (bs.StatusTypeID = t.StatusTypeID)
join [DeliveryPlan] dp on (dp.BaseSpecificationID = bs.BaseSpecificationID)
where
bs.BaseID = 130
and t.IsActive = 1
and dp.ItemID = @itemID
答案 1 :(得分:0)
这将以更好的方式执行,因为连接条件将缩小第一个go本身的行数,而不是等待where子句执行。两者的执行计划都不同(在哪里/不在哪里)。
UPDATE dp
SET Amount = dp.Amount + CASE
WHEN @useAmountColumn = 1
AND dbo.ConvertToInt( bs.Amount ) > 0 THEN dbo.ConvertToInt( bs.Amount )
ELSE @amount
END
FROM BaseSpecification bs
JOIN BaseSpecificationStatusType t ON
( bs.StatusTypeID = t.StatusTypeID
AND bs.BaseID = 130
AND t.IsActive = 1
)
JOIN DeliveryPlan dp ON
( dp.BaseSpecificationID = bs.BaseSpecificationID
AND dp.ItemID = @itemID
);
答案 2 :(得分:0)
如果更新部分中提到的问题是它随机出现,那听起来就像是参数嗅探不好。当问题发生时,您可以查看计划缓存以检查查询计划是否正常,如果没有,计划创建的值是什么(您可以在计划中最左边的对象中找到它们)以及示例使用sp_recompile,看看下次会有什么样的计划。