前言:统计信息作为sql server优化器生成执行计划的重要参考,需要数据库开发人员,数据库管理员对其有一定的理解,从而合理高效的应用,管理.
第一部分 概念
统计信息(statistics):描述某个(些)栏位,索引的数据分布情况.优化器用其评估生成高效执行计划.
密度(density):一个比率值,显示在一个(组)列中有多少唯一值.(实际应用中值越小越好)
Density = 1 / Number of distinct values for column(s)
直方图(histogram):将数据分割成不同的段(steps),用于描述,记录每段数据分布的具体情况(抽样创建).最多分为200 steps
DBCC show_statistics(object_name,Column_name)
Header(信息头)包含统计信息一系列元数据
Density(密度)包含列(列组)的密度信息及平均列(组)长度
Histogram(直方图)包含直方图描述信息.
Histogram(直方图)
RANGE_HI_KEY:直方图列(多列情况为首列记录)段的上限值.列值就是键值
RANGE_ROWS:其相应列值位于此段(不包含上限)的行得数量(估计值)
EQ_ROWS:等于其列值上限值的行数
DISTINCT_RANGE_ROWS: RANGE_ROWS中的非重复值数量
AVG_RANGE_ROWS:直方图段内值得平均行数(不包括上限)
DISTINCT_RANGE_ROWS > 0则为RANGE_ROWS / DISTINCT_RANGE_ROWS
第二部分 原理,应用
统计信息更新
统计信息可以人工维护更新或是由优化器在确认执行计划有效时依据之一:重编译阈值(recompilation threshold/RT)来决定统计信息是否过期而执行更新.
触发条件
当创建的表为空表时,添加一条数据则更新
当表数据小于500行时,记录更新标识(Modification Counters)大于500更新
当表数据大于500行时,记录更新标识大于500且20%行数变化(rowcnt)
注:临时表表很小(0行或者小于6行).6次变更触发更新.
表变量无统计信息
关于记录更新标识(Modification Counters)
Rowmodctr sql2000及之前使用.记录在sys.sysindexes中.
注:此参数虽然高版本依赖其使用,但微软目前仍维护此参数变化可作为参考
colmodctr sql2005及以后使用记录在sys.sysrscols. rcmodified中(需DAC访问)
此外DMV sys.system_internals_partition_columns的modified_count同样记录
Colmodctr(无需DAC)但不提供向上兼容.目前sql2012依然支持!
Colmodctr记录规则:
Insert 每添加一行所有列 Colmodctr+1=Colmodctr
Delete 每删除一行所有列Colmodctr+1=Colmodctr
Update 每修改一行 更新目标列Colmodctr+1=Colmodctr(sql2008+)
Sql2005更新目标列
当修改列为NOKEY columns时Colmodctr+1=Colmodctr
当修改列为KEY columns时Colmodctr+2=Colmodctr
Bulk Insert 与N Rows Insert类似
Truncate table 与N Rows delete类似
注: Modification Counters非事务(如当插入1000条数据,然后rollback. Colmodctr会加1000)
过滤统计信息(filtered statistics)触发更新为整体数据区间而非过滤区间.一旦创建需人工维护
优化器应用统计信息.
优化器如何应用统计信息是一个比较复杂的方式.Sql Server在各版本之间应用方式甚至不尽相同.这里只做简单介绍.
优化器使用Statistics”偏好” 优先考虑最新的,Full Scan的统计信息
简单介绍下等式单谓词预估.
dbcc show_statistics('votes','IX_MultiColumn1')
select * from votes where topic_id=40
当谓词命中边界值时预估行数为EQ_ROWS
select * from votes where topic_id=10000
当谓词值在某个区间内,非命中边界值,预估值为AVG_Range_ROWS.即9042至16234间的所有谓词键值预估均为2.482208
declare @topic_id int
set @topic_id =1000
select * from votes where topic_id=@topic_id
当谓词为变量形式时,优化器不知道参数值.将采用 密度*行数的形式预估.
即topic_id=@topic_id 为0.000004936151*1943794=9.59486
第三部分 维护
查看统计信息
sp_autostats 'votesbak'---查看统计信息更新信息
sp_helpstats 'votesbak','all' ---查看统计信息对应列/键值
dbcc show_statistics('votes','IX_MultiColumn1')—查看特定统计信息的详细内容
统计信息相关设置
AUTO_CREATE_STATISTICS ----自动创建统计信息
AUTO_UPDATE_STATISTICS ---自动更新统计信息
AUTO_UPDATE_STATISTICS_ASYNC --自动异步更新统计信息(优化器会用旧的统计信息,而不重编译,立即执行.)
例子:
ALTER DATABASE [BitautoReview2] SET AUTO_UPDATE_STATISTICS_ASYNC ON
Trace Flag 2371 弹性根据条件更新统计信息
统计信息操作
Create Statistics --创建统计信息
Update Statistics --更新统计信息
Drop Statistics --删除统计信息
维护统计信息时可选择样本量来进行创建,更新
update statistics [votes](IX_MultiColumn1) with fullscan--手动更新指定索引的统计信息(一般针对特定统计信息问题时使用全扫描.更新时间较长可能影响性能)
UPDATE STATISTICS Votes WITH SAMPLE 10 Percent;-----手动更新全表统计信息,样本采样10%(一般针对更新整个对象时使用,样本量与精确程度依环境而定)
UPDATE STATISTICS votes WITH ROWCOUNT =1000000,PAGECOUNT=100000---指定更新行数/页数(一般用于模拟当表数据量变得巨大时,优化器将采用何种执行计划)
统计信息最佳实践
AUTO_CREATE_STATISTICS , AUTO_UPDATE_STATISTICS一般无特殊应用自动打开.
AUTO_UPDATE_STATISTICS_ASYNC当触发更新的表巨大,统计信息更新会明显影响当前性能,且旧的统计信息对原有更新无明显影响时应设置为ON
Trace flag 2371 根据相应环境设置
由表变量造成的因无统计信息而使执行计划糟糕的情况用临时表代替
只读库(Readonly)配置前应创建相应统计信息
尽量避免变量,使用PROC传参形式,当使用动态SQL时用exec sp_executesql形式
过滤统计信息应人为维护
表达式(CTE)再参与Join的操作后,可能因执行逻辑无法获取准确统计信息,当出现此问题时用临时表或重写等方式代替
当数据倾斜很大,造成参数嗅探等问题时,应创建过滤统计信息(过滤索引),或是用query Hint,重写逻辑处理等方式处理.