SQL Server中扫描(scan)和查找(seek)这两种算法的区别

SQL SERVER使用扫描(scan)和查找(seek)这两种算法从数据表和索引中读取数据。这两种算法构成了查询的基础,几乎无处不在。Scan会扫描并且返回整个表或整个索引。 而seek则更有效率,根据谓词(predicate),只返索引内的一个或多个范围内的数据。下面将以如下的查询语句作为例子来分析scan和seek:

select OrderDate from Orders where OrderKey = 2

Scan

使用Scan的方式,SQL Server 会去读取Orders表中的每一行数据,读取的时候评估是否满足谓词 “where order=2”。如果满足(数据行符合条件),则返回该行。这个例子里,我们将这个谓词称作“residual predicate”。为了得到最优的性能,SQL会尽可能地在扫描中使用“residual predicate”。但如果residual predicate的开销过于昂贵,SQL Server可能会使用单独的“filter iterator”. “residual predicate”以where关键字的形式出现在文本格式的plan中。对XML格式的plan,则是<predicate>标记的形式。

下面这个扫描的文本格式的plan的结果:

   |--Table Scan(OBJECT:([ORDERS]), WHERE:([ORDERKEY]=(2)))

下图说明了扫描的方式:

无论数据行是否满足条件,扫描的读取方式都会访问表中的每一个数据,所以scan的成本和表的数据总量是成比例的。 因此,如果表很小或者表内的大多数数据多满足谓词,scan是一种有效率的读取方式。然而如果表很大或者绝大多数的数据并不满足谓词, 那么这种方式会让我们访问到太多不需要的数据页面,并执行更多的额外的IO操作。

Seek

继续以上面的查询为例子,如果在orderkey列上有一个索引,那么seek可能会是一个好的选择。使用seek的访问方式,SQL Server会使用索引直接导向到满足谓词条件的数据行。 这个例子里,我们将这个谓词称为“seek predicate”。 大多数情况下,SQL Server不必将“seek predicate”重新评估为“residual predicate”。 索引会保证“seek”只返回符合条件的数据行。“seek predicate”以seek关键字的形式出现在文本格式的plan中。 对于xml 格式的plan,则以<seekpredicates>标记出现。

下面是使用seek的文本格式的plan的结果:

|--Index Seek(OBJECT:([ORDERS].[OKEY_IDX]), SEEK:([ORDERKEY]=(2)) ORDERED FORWARD)

使用seek时,SQL Server只会直接访问到满足条件的数据行和数据页,因此它的成本只跟满足条件的数据行的及其相应的数据页面数量成比例, 和基表的数据量完全没有关系。因此,如果对于一个选择性很高(通过这个谓词,可以筛选掉表中的大部分数据)的谓词条件,seek是非常高效的。

下面的表格列出了seekscan这两种查找方式和堆表,聚簇索引和非聚簇索引的各种组合:

 ScanSeek
HeapTable Scan 
Clustered IndexClustered Index ScanClustered Index Seek
Non-Clustered IndexIndex ScanIndex Seek
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值