查询优化的统计信息是一些对象,这些对象包含与值在表或索引视图的一列或多列中的分布有关的统计信息。查询优化器使用这些统计信息来估计查询结果中的基数或行数。通过这些基数估计,查询优化器可以创建高质量的查询计划。例如,查询优化器可以使用基数估计选择索引查找运算符而不是耗费更多资源的索引扫描运算符,从而提高查询性能。
其实关于统计信息的作用通俗点将就是:SQL Server通过统计信息理解库中每张表的数据内容项分布,知道里面数据“心中有数”,这样每次查询语句的时候就可以根据表中的数据分布,基本能定位到要查找数据的内容位置。
比如,我记得我以前有篇文章写过一个相同的查询语句,但是产生了完全不同的查询计划,这里回顾下,基本如下:
SELECT * FROM Person.Contact WHERE FirstName LIKE 'K%' SELECT * FROM Person.Contact WHERE FirstName LIKE 'Y%' |
完全相同的查询语句,只是查询条件不同,一个查找以K开头的顾客,一个查找以Y开头的顾客,却产生了完全不同的查询计划。
其实,这里的原因就是统计信息在作祟。
我们知道,在这张表的FirstName字段存在一个非聚集索引,目标就是为了提升如上面的查询语句的性能。
但是这张表里面FirstName字段中的数据内容以K开头的顾客存在1255行,也就是如果利用非聚集索引查找的方式,需要产生1225次IO操作,这可能不是最糟的,糟的还在后面,因为我们获取的数据字段并不全部在FirstName字段中,而需要额外的书签查找来获取,而这个书签查找会产生的大量的随机IO操作。记住:这里是随机IO。
所以相比利用非聚集索引所带来的消耗相比,索引扫描来的更划算,因为它依次扫描就可以获取想要的数据。
而以Y开头的就只有37行,37行数据完全通过非聚集索引获取,再加一部分的书签查找很显然是一个很划算的方式。因为它数据量少,产生的随机IO量相对也会少。
所以,这里的问题来了:
SQL Server是如何知道这张表里FirstName字段中以K开头的顾客会比较多,而以Y开头反而少呢?。
这里就是统计信息在作祟了,它不但知道FirstName字段中各行数据的内