Sql server SQL Server 2012中的永无止境查询
SQL Server 2012,亚马逊RDS 这是我的简单问题Sql server SQL Server 2012中的永无止境查询,sql-server,amazon-web-services,sql-server-2012,Sql Server,Amazon Web Services,Sql Server 2012,SQL Server 2012,亚马逊RDS 这是我的简单问题 update [dbo].[DeliveryPlan] set [Amount] = dp.Amount + case when @useAmountColumn = 1 and dbo.ConvertToInt(bs.Amount) > 0 then dbo.ConvertToInt(bs.Amount)
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_分配为32,tembdb_当前为-32,读取为-32000000,cpu为-860000(查询持续20分钟)
有什么问题
更新:我通过
BaseSpecificationID+ItemID
为[DeliveryPlan]
添加了非聚集索引,问题消失了。不幸的是,我每天都在不同的查询中看到这个问题。问题会毫无疑问地消失。您可能会遇到基表的锁定条件
优化查询以直接更新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
这将以一种不同的方式更好地执行,因为连接条件将在第一次执行时减少行数,而不是等待执行where子句。两者的执行计划将不同(有何处/无何处)
如果更新部分提到的问题是它随机出现,那么听起来像是坏的参数嗅探。当问题发生时,您可以查看计划缓存以检查查询计划是否正常,如果不正常,创建计划时使用的值是什么(您可以在计划中最左侧的对象中找到它们)例如,使用sp_recompile,看看下次会得到什么样的计划。是否尝试将
dp.ItemID=@ItemID
移动到WHERE子句?我90%肯定这不会有帮助,但我对结果非常感兴趣。连接列上的索引呢?在过滤列上呢?查询计划有什么提示吗?表BaseSpecificationStatusType
的行数是多少?另一件事-我希望您了解数据库页面/行锁定过程。我想除了你没有人在使用数据库。。。还是?没人在用。BaseSpecificationStatusType-4或5行我只能看到带有另一个where条件的查询的计划我没有抓住要点:建议的解决方案是一个非常相同的查询,其筛选器从join
移动到where
子句。已测试的更改没有产生任何效果。@Paolo注意到更新
后的语句,原始查询是另一个交付计划
表,而不是使用dp
。因此,更新是更新所有行,而不是我现在看到的目标ItemID
@Paolo Opps,我认为在更新中不使用别名而使用表名是不合适的,但我错了。您的注释不是注释:应该放在答案内。还有,为什么你认为join会更快?你确定查询优化器不会选择同样的方式来处理它们吗?同样,这不是一个评论:关于你的答案的所有细节(你为什么提出它,技术细节等等)都必须放在答案中,在那里可以一次全部阅读,而不必在评论列表中查找。请完成您的回答。我试图在sp中重新定义参数,以更改此错误的参数嗅探,据我所知,这是过时统计数据的结果。而且统计数据很好。@MihailKatrikh参数嗅探可以发生,即使统计数据100%准确,并且您的数据可能会导致某些ID需要与其他ID不同的计划。在业绩不佳时查看计划,应该会让你对会发生什么有所了解
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
);