在sqlserver中,优化器如何利用统计信息来估算返回的行数(三)

来看看多列过滤是如何估计返回的行数

use AdventureWorks
go
--把毫秒全置为0,便于看到效果
update dbo.DatabaseLog 
set PostTime=cast(CONVERT(varchar,PostTime,120) as datetime)
update statistics DatabaseLog with fullscan

--创建event索引
create index idx_event on dbo.DatabaseLog(Event) with(online=on)

 

  1. 看如下的SQL,过滤字段上分别建有索引
select * from dbo.DatabaseLog 
where PostTime='2006-04-26 11:44:31.000' 
and event='CREATE_TABLE'
OPTION
(
    QUERYTRACEON 3604,
    QUERYTRACEON 9292,
    QUERYTRACEON 9204
)

如下的执行计划:

在sqlserver中,优化器如何利用统计信息来估算返回的行数(三)_第1张图片

 

idx_postTime 估计返回的行数为56,来自于统计信息的直方图:

在sqlserver中,优化器如何利用统计信息来估算返回的行数(三)_第2张图片

idx_event 估计返回行数为69,也是来自直方图:

在sqlserver中,优化器如何利用统计信息来估算返回的行数(三)_第3张图片

那merge Join预估返回的行数10怎么算出来的?merge join 返回的结果应该是idx_postTime结果集,

idx_event结果集的交集。databaselog的行数为389行。

merge join 返回的行数: (56./389)*(69./389)*389=9.933052046574,优化器据此估算merge join

操作符返回的行数。

优化器在运行期间,确实是加载了idx_postTime/idx_event上的统计信息,如下图所示:

image

 

同时注意,key_Lookup操作符,预估返回的行数是一行,这个行数是执行一次返回的行数,而这个key_lookup操作执行了56次,所以实际

返回的行数为56行,预估行数=实际行数,如下图所示:

在sqlserver中,优化器如何利用统计信息来估算返回的行数(三)_第4张图片

 

2.来看下面SQL返回的行数:

dbcc FreeProcCache
select * from dbo.DatabaseLog 
where PostTime='2006-04-26 11:44:31.000' 
or event='CREATE_TABLE'
OPTION
(
    QUERYTRACEON 3604,
    QUERYTRACEON 9292,
    QUERYTRACEON 9204
)

这个是全表扫描,如图所示:

在sqlserver中,优化器如何利用统计信息来估算返回的行数(三)_第5张图片

 

这个预估的行数:postTime 返回的56+event 返回的69-交集的部分9.933052046574=115.067行,

其中,扫描全表时也加载了postTime/event上手动新建的统计信息,如图所示:

 

image

 

总结:对于单独的列上建立的索引,优化器根据每个列上的统计信息来预估返回的行数,无论后续执行时是访问索引还是访问基表获得数据!

你可能感兴趣的:(sqlserver)