《Microsoft Sql server 2008 Internals》读书笔记订阅地址:
http://www.cnblogs.com/downmoon/category/230397.html/rss
《Microsoft Sql server 2008 Internals》索引目录:
《Microsoft Sql server 2008 Internal》读书笔记--目录索引
上篇主要介绍了筛选统计和字符串统计、基线估计,本文将关注Limitation和Costing
■限制(limitation)
SQL Server的基线估计通常是很棒的。不幸的是,制作一个适合所有应用程序的每一个查询的完美模型是不可能的,尽管大部分的操作是在内部进行的,但还是有一些可以帮助我们更好地了解查询结构:
1、Multiple predicates in an opeartor
在基线估计为整个操作决定结果估算时,多谓词的可选择性是相乘的。这意味着谓词被假定为相互独立的。实际上,大多数的被统计数据在两列之间是相对独立的。随着查询中谓词的增加,查询优化器实际上不可能直接相乘完事,因此,多谓词的操作的可选择性比你想像的大得多。
2、Deep Query Trees
基于树结构的基线估计的处理机制很好,但同时也意味着查询树很低级的错误通过向上的计算进程被放大了。结果,使用为查询树的更高部分的直方图的深查询树完全停止,可能使用简单的启发式制作基准估计以避免数据的假定设定可能是无效的。
3、Less common operators
查询优化器有很多操作符。一些不常见的操作符可以通过Set Statistics Profile ON来查看评估是否恰当。
■成本(Costing)
估计基准是通过逻辑树完成的。成本就是潜在的选择计划运行时将会消耗多少时间。每个计划都是独立的。查询优化器考虑不同的物理计划得出相同的结果。成本是一个在哈希连接和循环连接,或一个连接与另一个连接顺序之间选择的组件。
成本后面的idea其实非常简单。使用基准估计和一些关于给中每列的平均值和最大值的附加信息,成本组件能决定在每个数据页适合多少行。每个操作的成本累加为总成本。查询优化器在优化期间能够从可能的计划集合中选择最快(成本最低)的查询计划。
实际上,成本并不这么简单,在I/O顺序间(也就是磁盘块被序列化存储在磁盘上地方)有成本差异。有些查询足够大以至于数据能被读进内存,并在一个查询中多次读取。这些读取的额外信息将要从内存页缓冲池被读取到数据页,从而避免了直接从磁盘上直接读取。更进一步,有些查询需要的内存会超出服务器的可用内存,此时,成本组件需要去决定哪些页需要被从缓冲池中移走,并需要被随机或顺序的再读取。优化器会使用逻辑考虑所有的条件,决定哪个操作将消耗多长时间去计算的处理的精确成本,所有这些考虑将确保SQL Server尽可能最佳地为每个查询选择一个棒的查询计划。
为了使查询优化器更加兼容,SQL Server开发团队在创建成本模型时使用了几个假定。
1、一个查询被假定从一个cold cache开始。也就是每个查询处理器假定每个初始的I/O都是直接从磁盘读取。
2、随机I/O,即每次读取完全是离散的。即不考虑索引和数据页结构。这样可能比实际用到的时间要少。
查询优化器在内建的成本模型中还有另一些假定。一个假定与客户如何读取查询结果有关。成本组件假定每个查询读取查询结果的每行。然而,一些客户端仅仅读取一些行,并关闭查询。比如有时你希望从10000行记录中查找40页显示在页面。此时,如果查询优化器知道用户将要使用的行数,它将会为这个特定的需求制定特别的优化。通常,这会引起查询优化器从哈希连接这样的操作符转换为嵌套的循环连接,前者在查询开始时启动成本很高,而后者启动成本很低,但是每行成本很高。
在这种状况下,SQL Server展示了一种叫"Fast N"的隐射。如果一个用户通常只读取行的一个子集,它传递选项(FAST N)给查询,从而在整个查询优化器中只返回N行而不是所有行。我们看示例:
go
Create clustered index i1 on tb2010A(col1)
go
set nocount on
BEGIN TransAction ;
Declare @i int
set @i = 0
while @i < 10000
BEGIN
Insert into tb2010A(col1) values ( @i );
set @i = @i + 1
END
Commit Transaction
go
我们比较一下Option(Fast N)的查询计划:
本文主要介绍了Limitation和Costing,至此,介绍完了几个重要的概念:统计,基线估计,成本。下文的主题是索引选择(Index Selection)