本文是翻译Brent Ozar的这篇文章Updating Statistics Causes Parameter Sniffing, 译文地址https://www.cnblogs.com/kerrycode/p/19542136。
在我的免费课程如何像引擎一样思考中,我解释了SQL Server是如何基于统计信息来生成执行计划的。表中的数据内容会决定它使用哪些索引、采用索引查找还是全表扫描、分配多少CPU核心、授予多少内存,以及诸多其它执行策略。
当对象的统计信息发生变化时,SQL Server 会认为 “下次有查询引用这个对象时,我最好生成一个新执行计划,因为旧执行计划可能不再适合新的数据分布”。
这通常是好事,因为我们都希望有一个准确的执行计划。但这同时也让你面临/陷入风险。
每当你更新某张表或某个索引的统计信息时,其实也是在告诉 SQL Server,所有涉及该表的执行计划都需要根据接下来传入的参数生成一个全新的执行计划。正如我在Fundamentals of Parameter Sniffing课程中所讨论的,这意味着你更新统计信息次数越频繁,承担的风险就越大:你是在刻意释放执行计划缓存的一部分,通常是很大一部分,并且对接下来传入的参数抱有很大的不确定性。
更新统计信息可以生成更优的查询计划.
在理想情况下,你应该只有在查询计划能从新的统计信息中获益时,才应该更新统计信息.
为了让大家理解这一点,我们以Stack Overflow数据库中的 Users 表为例,并思考一下每一列的内容会以何种方式发生变化,才会对查询计划产生影响。
频繁更新统计数据至关重要的经典场景是使用日期列来记录当前活动.在数据仓库中,这意味着加载昨天的新销售数据。在Stack Overflow的Users表中,类似的是LastAccessDate 列:用户整天都在登录。假设我们在 LastAccessDate 上有一个索引,并且有一个存储过程通过该日期范围来查询用户信息:
[code]CREATE INDEX LastAccessDate ON dbo.Users(LastAccessDate);GOCREATE OR ALTER PROC dbo.usp_SearchUsersByDate @LastAccessDateStart DATETIME, @LastAccessDateEnd DATETIMEASSELECT *FROM dbo.UsersWHERE LastAccessDate >= @LastAccessDateStart AND LastAccessDate = @LastAccessDateStart AND LastAccessDate |