MSSQL执行计划利用统计信息对数据行的预估原理以及SQL Server 2014中预估策略的改变
Tags: MSSQLSQL Server统计信息
前提
本文仅讨论SQL Server查询时,
对于非复合统计信息,也即每个字段的统计信息只包含当前列的数据分布的情况下,
在用多个字段进行组合查询的时候,如何根据统计信息去预估行数的。
利用不同字段的统计信息做数据行数预估的算法原理,以及SQL Server 2012和SQL Server 2014该算法的差异情况,
这里暂时不涉及复合统计信息,暂不涉及统计信息的更新策略及优化相关话题,以及其他SQL Server版本计算方式。
统计信息是什么
简单说就是对某些字段的数据分布的一种描述,让SQL Server在根据条件做查询的时候,大概知道预期的数据大小,
从而指导生成合理执行计划的一种数据库对象
统计信息的分类
索引上会自动创建统计信息,SQL Server也会根据具体的查询,在某些非索引自动创建索引,当然也可以通过手动方式创建统计信息。
先来直观地了解一下统计信息长什么样,参考截图,就是这么个样子,
_WASys****开头的是系统根据需要创建的统计信息,
与索引同名的是索引上创建的统计信息,
手动创建统计信息也可以在满足SQL Server命名要求的情况下自行命名。
下面一个是索引的统计信息。
统计信息的作用
查询引擎根据统计信息提供的数据做出合理的执行计划。
那么,查询引擎究竟是怎么利用统计信息做预估的呢,
以及下面将要提到的SQL Server 2014中较之前的版本有哪些变化?
本文将对此两点做一个简单的分析来说明SQL Server是怎么根据统计信息做估算的,下面开始正文。
测试环境搭建
习惯性地做一个演示的环境,创建一个表,写入100W的数据后面测试用。
(javascript:void(0);)
1 2 3 4 5 6 7 8 9 | create table TestStatistics ( Id int identity(1,1), Status1 int, Status2 int, Status3 int ) insert into TestStatistics values (RAND()*1000,RAND()*250,RAND()*50) go 1000000 |
(javascript:void(0);)
表中有四个字段,第一个是自增列,主要看Status1,Status2,Status3这三个字段,
三个字段的取值都是用随机数乘以一个常量系数的出来的,
因此这三个字段的数据分布范围分别是
Status1:0-999(1000种数据分布)
Status2:0-249(250种数据分布)
Status3:0-49(50种数据分布)
这个后面有用。
首先在SQL Server 2012中做测试
先做这么一个查询:select * from TestStatistics where Status1=885 and Status2=88 and Status3=8
这个查询完成之后,表上自动创建一个三个统计信息,
这三个统计信息分别是Status1,Status2,Status3这个三个字段的数据分布描述
首先来看一下其中这个_WA_Sys_00000002_0EA330E9,也即Status1这个列的统计信息的详细信息,
注意All density字段值,选择性是反应一个表中该字段的重复数据有多少或者说唯一性有多少,
计算方法是:1/表中该字段非重复个数。
上面说了,这个Status1这个列的取值范围是0-999,一共有1000中取值可能行,
那么这个选择行就是1/1000=0.001,所以也是吻合这里的All density=0.001的
照这么计算,其余两个字段的选择度分别是1/250=0.004 和1/50=0.02,分别如下截图的 All density。
执行计划对数据行的预估
说完统计信息的基础问题之后,我们就可以来观察执行计划对目标数据的预估规律了。
我们来看这么一个查询,如下,注意这个是查询的条件是参数变量,而不是直接的值,后面我会解释为什么这么做。
来观察执行计划对数据行的预估:可以看出来,预估为4行。