基数评估
目录
说明
基数评估是Cost的指标之一,会对执行计划影响,从而影响查询的性能。
基数评估准确的重要性
基数评估组件提供一下信息:
1.响应行数评估
2.不同值评估
3.不同值个数评估
4.从上游输入的重复值个数
基数评估是通过计算统计信息的出来的结果。
基数评估主要回答以下几个问题:
1.一个或多个谓词或过滤几行
2.2个表之间的连接谓词会过滤几行
3.预计一个指定列集合中有多少不同值
每个执行计划中的运算符都有评估值输入,这个值决定了优化器使用什么算法的操作符,同时也决定了最终的执行计划。
模型假设
基数评估有一下假设:
Independence:在不同列中存的数据是独立的
Uniformity:数据是均匀分布的
Containment:如果有查询,那么会假设是存在的。如2个表连接,那么不同值少的一定被不同值多的包含。
Inclusion:如果对一列对常数过滤,那么认为这个常数一定存在在这个列中。
启用新的基数评估
当数据库的兼容级别为120的时候,就是启用了新的基数评估,默认使用新的基数评估。
但是可以通过查询跟踪标记来指定:
2312:在兼容级别低于120的时候使用新的基数评估
9481:在兼容级别在120下,使用老的基数评估
验证基数评估的版本
可以从图形执行计划或者XML执行计划中找到CardinalityEstimationModelVersion,如果为120就是新的基数评估,70就是老的基数评估。
在迁移到新的基数评估前要测试
新的基数评估虽然总体提示了性能,但是对个别查询来说,会被影响,性能变差,所以要测试。
1.在类似生产环境下,测试大多数的符合
2.可以先迁移到sql server 2014,但是使用不运行在120兼容级别
3.也可以到120兼容级别,但是在全局范围开9481跟踪标记
4.新建数据库默认会使用120兼容级别。
验证基数评估
验证基数评估值,没有什么特别的就是通过实际值和评估值对个对比。
偏差问题
评估值偏差,是存在的,那么多少算是偏差太大了?其实没有一个固定的值,主要是看以下2点:
1.偏差是不是造成了资源过度使用
2.偏差是不是造成了特定查询的性能问题
如果任意一个出现问题的话,那么就能认为偏差太大了。
需要参与的变化
只有评估值变化的情况下,看性能是否下降超过预期,如果超过要进行手动干预。
当性能下降时的动作
1.能够从新基数评估得到性能优化的查询,就使用新基数评估,其他的进行重新调整。
2.有好处的查询使用新的基数评估,其他的使用跟踪标记9481
3.使用老的基数评估,特定的查询可以指定跟踪标记2312
4.直接调试有问题的sql
5.使用老的基数评估
SQL Server 2014中的修改
增加多个谓词的相关性的假设
在没有多列统计信息的情况下,SQL Server优化器会认为谓词之间是不相关的。
老的基数评估:各个谓词的选择度相乘
新的基数评估:
修改超出统计信息范围的评估
如果超出统计信息范围,那么老的基数评估就认为不存在,评估行数为1。
新的基数评估会用,密度*总行数来当评估行数。
Join评估算法修改
简单Join
老的基数评估是以线性增长的方式一步一步对齐2个柱形图,新的基数评估,只是用柱形图的最大最小边界来对齐。(文章并没有给出算法很坑爹和没说一样)。
新的基数评估是用这种原则,很容易发现评估值不够准确。
多Join条件
多个join条件,对于老的基数评估来说,是独立的谓词,是用选择度相乘的方法来组合。
新的基数评估,是用2个不同值个数中较小的一个,然后乘以2边的平均频率。(搞不懂)
Join带相等和不相等的谓词
老的基数评估,是独立的谓词,是用选择度相乘的方法来组合。
新的基数评估,认为大表小标多对1的关系。即大表中的一行,必定存在于表的一样与之对应。这个算法把大表的评估作为评估。(这个简单)
Join包含(Containment)假设的修改
如果是等值连接,那么就会假设这个列表2边都是存在的。如果存在join表上有非join谓词,老的基数评估那么会认为一些级别的相关,这种相关叫做简单包含(Simple Containment)。
老的基数评估的JOIN评估,假设在使用join谓词之前,任意存在的谓词会缩小柱形图,而谓词之间是不相关的。
新的基数评估是使用基本包含(Base Containment),新的基数评估,是直接从基表上面获取选择度,而不是经过谓词过滤之后(虽然知道假设被修改了也搞不懂有啥好处)。
不同值计数评估的变化
对于新的基数评估和老的相比在多对多连接中,不同值计数评估相差很小。如果join条件会放大基数,老的基数评估可能会不准确。
新的基数评估根据join谓词和非join谓词选择不同值。新的基数评估使用环境基数(ambient cardinality),环境基数是group by或者distinct列的最小不同值集合(完全搞不懂)。
诊断输出
使用新的xevent,query_optimizer_estimate_cardinality来输出
CREATE EVENT SESSION [CardinalityEstimate] ON SERVER
ADD EVENT sqlserver.query_optimizer_estimate_cardinality
ADD TARGET package0.event_file( SET filename = N‘S:\CE\CE_Data.xel‘ ,
max_rollover_files =( 2 ) )
WITH ( MAX_MEMORY = 4096 KB ,
EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS ,
MAX_DISPATCH_LATENCY = 30 SECONDS ,
STARTUP_STATE = OFF );
GO
-- Start the session
ALTER EVENT SESSION [CardinalityEstimate] ON SERVER STATE=START;
--
-- Your workload to be analyzed executed here (or in another session)
--
-- Stop the session after the workload is executed
ALTER EVENT SESSION [CardinalityEstimate] ON SERVER STATE=STOP;
也可以使用A first look at the query_optimizer_estimate_cardinality XE event中的方法。
新基数评估的调试方法
自己看白皮书
参考:Optimizing Your Query Plans with the SQL Server 2014 Cardinality Estimator