先从一个问题开始:
我知道统计信息是为查询引擎做查询计划用的,现在有以下请教大家,谢谢!
1.统计信息是什么时候会自动建立与更新,Insert、update、delete时候会自动更新统计信息吗?
2.当我把数据库设置中的"自动创建统计信息"与"自动更新统计信息"设置为True,我还需要建立维护计划中建立计划维护统计信息吗?此处的自动建立与更新在什么时候会自动更新?
3.当我修改表结构与dbcc dbreindex时都会自动更新表或view的统计信息吗?
4.统计信息更新与建立时是生成一些什么信息?
对上述问题的回复:
1、只要你在数据库设置中的"自动创建统计信息"与"自动更新统计信息"设置为True,那么在语句执行时,不管是update、delete、还是select语句,就会根据where条件中的字段,自动设置统计信息。
但insert 语句运行时,应该不会建立统计信息。
2、虽然设置了自动更新或创建统计信息的设置为true,但是所谓自动更新统计信息,是按照你对数据修改的数量来决定的,sql server有一些内部的判断条件,比如修改的数据占到整个表的百分之多少后,才会更新统计信息,这个不是很准确的。
所以还是需要你通过,update statistics 表 来更新统计信息。
3、如果你没有删除那个统计信息涉及到的列,应该不会重新生成。
4、通过:dbcc show_statistics('表',统计名称)
我做了一个实验,下面的代码,需要一步一步运行,前后对比:
--1.建表
select * into tb_object
from sysobjects
--2.查询统计信息,发现还没有创建
select *
from sys.stats
where object_id = object_id('tb_object')
--3.通过where条件查询1条记录
select *
from tb_object
where ID = 3
--4.发现,已经创建了统计信息
select *
from sys.stats
where object_id = object_id('tb_object')
/*
object_id name stats_id auto_created user_created no_recompute has_filter filter_definition
389576426 _WA_Sys_00000002_173876EA 2 1 0 0 0 NULL
*/
--5.这个统计信息,到底是什么东东呢?
dbcc show_statistics('tb_object', --表名
_WA_Sys_00000002_173876EA --统计信息的名称
)
/*
Name Updated Rows Rows Sampled Steps Density Average key length String Index Filter Expression Unfiltered Rows
_WA_Sys_00000002_173876EA 11 11 2013 1:14PM 59 59 42 1 4 NO NULL 59
All density Average Length Columns
0.01694915 4 id
RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
3 0 1 0 1
7 1 1 1 1
8 0 1 0 1
17 0 1 0 1
19 0 1 0 1
23 0 1 0 1
25 1 1 1 1
29 1 1 1 1
34 0 1 0 1
41 0 1 0 1
44 0 1 0 1
46 0 1 0 1
49 0 1 0 1
51 1 1 1 1
54 0 1 0 1
55 0 1 0 1
58 0 1 0 1
60 1 1 1 1
64 0 1 0 1
65 0 1 0 1
69 2 1 2 1
73 2 1 2 1
75 1 1 1 1
78 0 1 0 1
82 0 1 0 1
85 0 1 0 1
90 0 1 0 1
92 1 1 1 1
94 1 1 1 1
96 1 1 1 1
98 1 1 1 1
53575229 0 1 0 1
69575286 0 1 0 1
181575685 0 1 0 1
229575856 0 1 0 1
373576369 0 1 0 1
389576426 0 1 0 1
1977058079 0 1 0 1
2009058193 1 1 1 1
2041058307 1 1 1 1
2073058421 1 1 1 1
2089058478 0 1 0 1
*/
其实,统计信息中存放的就是一个关于某列的“统计”的信息,你看上面的输出,就是一个直方图,每个id值,会出现多少次,也就是有多少行信息,以利于优化器,做出正确的判断。比如,id这列,假设,当你的语句是select * from tb_object where id = 3
而id = 3的记录,有100w条,而整个表的记录就500w条,那么sql server优化器知道后,可能就会采用表扫描的执行计划了。
相应的,如果id = 3的记录只有1000条,而表有100w条记录,那么sql server会考虑采用索引查找的方式,来获取数据。