先来看一幅图:
优化器是根据统计信息来生成执行计划的,具体来说是根据物理操作符(physical operator)预估返回的行数来生成执行计划的,
优化器预先是不知道真实数据分布情况的,所以统计信息准确与否直接决定了执行计划的优劣
先来看过滤条件为一个字段是如何评估返回的行数?
use AdventureWorks
go
create index idx_postTime ondbo.DataBaseLog(posttime) with(online=on)select * from dbo.DatabaseLogwhere PostTime='2006-04-26 11:44:30.217'OPTION
(QUERYTRACEON 3604,QUERYTRACEON 9292,QUERYTRACEON 9204)
option() 使用来查看生成执行计划过程中,优化器加载了那些统计信息:
可以看到使用到了indexid=3的统计信息,那对应的统计信息名是什么呢?使用如下的脚步可以看到:
use AdventureWorks
go
select object_name(s.object_id) as tbname,s.name as stastistics_name,
COL_NAME(s.object_id,c.column_id) as stats_column,
s.stats_id ,i.rowcnt,i.rowmodctr,stats_date(s.object_id,s.stats_id) as updated_time
from sys.sysindexes as iinner join sys.stats as son i.id=s.object_id
and i.indid=s.stats_id
inner join sys.stats_columns con c.object_id=s.object_id
and c.stats_id=s.stats_id
where i.id in(object_id('DatabaseLog'))
结果是:
即为刚新建的索引所对应的统计信息。需要说明的是,对于手动新建的索引,其index_id是为统计信息的stats_id
再来看看该列上的 直方图:
DBCC show_statistics(DatabaseLog,idx_postTime)
EQ_ROWS=1,所以执行计划中预估的返回行数为1,如下图所示:
Actual Number of Rows = Estimated Number of Rows,所以生成的是最优的执行计划
总结:对于相等性的过滤条件,且没有使用到参数,如 [where PostTime='2006-04-26 11:44:30.217'],
优化器是直接使用直方图来评估返回的行数!