SQL Server统计信息由索引创建或自动启用时生成,含统计头、密度向量和直方图三部分;直方图最多200步且受8KB页限制,导致粒度不足、列间独立性假设失效及统计滞后,引发基数估算错误,进而造成执行计划低效。

统计信息怎么来的
SQL Server在创建索引或启用自动创建统计信息后,会为关键列生成统计对象。它包含三部分:统计头(更新时间、行数等元数据)、密度向量(反映多列组合的唯一性程度)、直方图(描述首列的数据分布)。直方图最多200个步长,受限于8KB页大小——数据量越大,单一步长覆盖的值范围越宽,分布刻画就越粗糙。
基数估算为什么会出错
误差主要来自三方面:
- 直方图粒度不足:比如某列有上千万不同值,但直方图只能分200段,高频值区域可能被压缩成1步,低频长尾被忽略,导致对WHERE条件返回行数严重误判。
- 列间独立性假设失效:优化器默认认为colA和colB取值无关,但现实中常存在强相关(如“订单状态=已发货”时,“发货时间”几乎必然非空)。这种关联性无法被密度向量或直方图捕获。
- 统计信息滞后:数据批量导入或高频更新后未及时UPDATE STATISTICS,行数、分布等元数据就变成“过期快照”,估算自然失真。
误差引发的具体执行问题
低估或高估基数,会直接扭曲优化器的成本计算:
- 低估过滤效果:以为WHERE只返回10行,实际返回10万行 → 选Nested Loops连接,每行触发一次键查找,I/O暴增;本该用Hash Join却没选。
- 低估聚合/排序数据量:内存授予按预估100MB分配,实际要5GB → 溢出到tempdb,磁盘排序拖慢整个查询。
- 误判并行价值:预估总成本低,禁用并行 → 大数据量下串行处理耗时翻倍。
- 索引弃用:误判某索引选择率差,宁可全表扫描也不走索引,尤其在复合索引中首列分布偏斜时更明显。
怎么缓解估算偏差
不是所有场景都靠“更新统计信息”就能解决:
- 对倾斜数据(如90%记录status='active',其余分散在10个状态),用red">过滤统计信息单独为status!='active'建统计,让小比例值获得专属直方图。
- 多列强相关查询(如WHERE a=1 AND b=2),考虑创建带INCLUDE列的索引,或用查询提示OPTION (USE HINT('ASSUME_JOIN_PREDICATE_DEPENDS_ON_FILTER'))(SQL Server 2016+)。
- 关键报表SQL若反复因CE版本切换性能波动,可用QUERYTRACEON(9481)或(2312)锁定估计器,比全局改兼容级别更精准。
- 定期检查sys.dm_db_stats_properties,对last_updated早于7天或修改行数占比超5%的统计对象主动更新。










