您好,欢迎访问一九零五行业门户网

第十二章SQLServer统计信息(2)非索引键上统计信息的影

前言: 索引 对性能方面总是扮演着一个重要的角色,实际上,查询优化器首先检查谓词上的 统计 信息 ,然后才决定用什么 索引 。一般情况下,默认会在创建 索引 时, 索引 列上均创建 统计 信息 。但是不代表在非 索引 键上的 统计 信息 对性能没有用。 如果
前言:        索引对性能方面总是扮演着一个重要的角色,实际上,查询优化器首先检查谓词上的统计信息,然后才决定用什么索引。一般情况下,默认会在创建索引时,索引列上均创建统计信息。但是不代表在非索引键上的统计信息对性能没有用。
        如果表上的所有列都有索引,那么将会是数据库负担不起,同时也不是一个好想法,包括谓词中用到的所有列加索引同样也不是好方法。因为索引会带来负载。因为需要空间存放索引,且每个dml语句都会需要更新索引。
        一般来说,建议在where或者on子句中出现的列上添加索引,但是由于某些情况,很难在所有的谓词上都创建索引,此时创建统计信息会是一个最起码的改进。如果auto_create_statistics为on,那么优化器会帮你做这一步。
准备工作:默认情况下,auto_create_statistics在数据库级别是设为on的,但是为了下面需要这里先改成off:
alter database adventureworks2012 set auto_create_statistics offgoalter database adventureworks2012 set auto_update_statistics offgo
然后创建一个新表用于本文使用:
select *into salesorddemofrom sales.salesorderheadergo
步骤:1、  对于新表,现在是没有统计信息在上面的,可以使下面语句来验证:
select object_id , object_name(object_id) as tablename , name as statisticsname , auto_createdfrom sys.statswhere object_id = object_id('salesorddemo')order by object_id desc go
因为没有统计信息,所以这个查询是没有数据的。
2、  现在在新表上创建一个聚集索引:
create clustered index idx_salesorddemo_salesorderid on salesorddemo(salesorderid)go
3、  再次运行步骤一的脚本,可以看到已经有了数据,现在来执行下面的语句,并开启执行计划:
select s.salesorderid , so.salesorderdetailidfrom salesorddemo as s inner join sales.salesorderdetail as so on s.salesorderid = so.salesorderidwhere s.duedate = '2005-09-19 00:00:00.000'

4、  下面截图是步骤3中的执行计划,关注一下salesorddemo表上有聚集索引扫描,这是合理的,因为没有where子句在使用salesorderid列。而salesorderdetails表有非聚集索引扫描。还可以看到实际行数和估计行数有很大差异。
5、  现在是时候在新表的duedate上创建统计信息,因为在查询中这个列并不包含在索引里面。
create statistics st_saledorddemo_duedate on salesorddemo(duedate)go
6、  再次执行步骤3的脚本,不需要任何改动:
select s.salesorderid , so.salesorderdetailidfrom salesorddemo as s inner join sales.salesorderdetail as so on s.salesorderid = so.salesorderidwhere s.duedate = '2005-09-19 00:00:00.000'

7、  对比上面的执行计划,此时在salesorderdetails表上已经从非聚集索引扫描变成了聚集索引查找,且开销只有2%,更总要的是实际行数和预估行数相差无几:
分析:如果优化器可以获得谓词上列的统计信息,那么相会知道将要返回的行数,并且帮助优化器选择最佳的执行方式。
其它类似信息

推荐信息