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是非常高效的。

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

        Scan Seek
Heap Table Scan  
Clustered Index Clustered Index Scan Clustered Index Seek
Non-Clustered Index Index Scan Index Seek
 
 

index seek与index scan

 

低效 Index Scan(索引扫描):就全扫描索引(包括根页,中间页和叶级页):

高效

Index Seek(索引查找):通过索引向前和向后搜索 :

解释解释index seek和index scan: 索引是一颗B树, index seek是查找从B树的根节点开始,一级一级找到目标行。 index scan则是从左到右,把整个B树遍历一遍。 假设唯一的目标行位于索引树最右的叶节点上(假设是非聚集索引,树深度2,叶节点占用k页物理存储)。 index seek引起的IO是4,而index scan引起的IO是K,性能差别巨大。

seek:从B树根到叶节点的过程 扫描:当SEEK完成后,在叶节点执行范围或全部扫描(按查询的选择性会有不同

关于索引,可以仔细读读联机文档关于物理数据库体系结构部分      查询条件中不要包含运算

这些运算包括字符串连接(如:select * from Users where UserName + ‘pig’ = ‘张三pig’),通配符在前面的Like运算(如:select * from tb1 where col4 like ‘�’),使用其他用户自定义函数、系统内置函数、标量函数等等(如:select * from UserLog where datepart(dd, LogTime) = 3)。

SQLServer在处理以上语句时,一样没办法估算开销。最终结果当然是clustered index scan或者table scan了。

查询条件中不要包含同一张表内不同列之间的运算

所谓的“运算”包括加减乘除或通过一些function(如:select * from tb where col1 – col2 = 1997),也包括比较运算(如:select * from tb where col1 > col2)。这种情况下,SQLServer一样没办法估算开销。不论col1、col2上都有索引还是创建了col1、col2上的覆盖索引还是创建了col1 include col2的索引

但是这种查询有解决办法,可以在表上多创建一个计算字段,其值设置为你的“运算”结果,再在该字段上创建一个索引,就Ok了。

(结果集/总行数)被称为选择性,比值越大,选择性就越高。

你得到了它,本文的重点就是选择性。

统计信息,说白了,就是表中某个字段取某个值时有多少行结果集。统计信息可以说是一种选择性的度量,SQLServer就是根据它来估算不同查询计划的优劣。

若表中总行数为1w,采样行数为1w。provider_no值为21的只有1行,而值为500的行则有4824行。

我们知道,SQLServer会缓存查询计划,假如有这么一个存储过程:

create proc myproc

(

@pno int

)

as

select * from charge where provider_no = @pno

第一次我们传进来一个21,OK,它会缓存该存储过程的执行计划为nonclustered index seek那个。后来我们又传进来一个500,完蛋了,服务器发现它有一个myproc的缓存,so,又通过nonclustered index seek执行,接着你的同伙看到你的查询花费了巨量的IO,于是,你被鄙视了。

这说明了啥?说明如果你的查询选择性变动剧烈,你应该告诉SQLServer不要缓存查询计划,每次都应该重新评估、编译。实现方法很简单,查询的尾巴上加一个option(recompile)好了。而且SQL2k5还有一个nb的 feature,可以每次只重新编译存储过程的一部分(当然,你也可以选择重新编译整个存储过程,这取决于你的需求。详见联机文档。)

 
 

SQL Server中SCAN 和SEEK的区别的更多相关文章

  1. SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别

    SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别 MSSQL为我们提供了两种动态执行SQL语句的命令,分别是 EXEC 和 SP_EXECUTESQL ,我们先来看一下两种方 ...

  2. [转]SQL SERVER中openrowset与opendatasource的区别

    本文转自:http://blog.sina.com.cn/s/blog_6399df820102vyy8.html SQL SERVER中openrowset与opendatasource的区别: o ...

  3. SQL SERVER 中的smalldatetime和datetime区别

    原文:SQL SERVER 中的smalldatetime和datetime区别 smalldatetime不能到秒. 不過它占的空間小.(4位) datetime(8位) 而且兩者的時間範圍不一樣. ...

  4. SQL Server中char与varchar数据类型区别

    在SQL Server中char类型的长度是不可变的,而varchar的长度是可变的 . 存入数据时: 如果数据类型为char时,当定义一个字段固定长度时,如果存进去数据长度小于char的长度,那么存 ...

  5. SQL Server中Text和varchar(max) 区别

    SQL Server 2005之后版本:请使用 varchar(max).nvarchar(max) 和 varbinary(max) 数据类型,而不要使用 text.ntext 和 image 数据 ...

  6. SQL Server中存储过程与函数的区别

    本质上没区别.只是函数有如:只能返回一个变量的限制.而存储过程可以返回多个.而函数是可以嵌入在sql中使用的,可以在select中调用,而存储过程不行.执行的本质都一样. 函数限制比较多,比如不能用临 ...

  7. SQL Server中DELETE和TRUNCATE的区别

    ​DELETE和TRUNCATE语句之间的区别是求职面试中最常见的问题之一.这两条语句都可以从表中删除数据.然而,也有不同之处. 本文将重点讨论这些差异,并通过实例加以说明. TRUNCATE DEL ...

  8. SQL Server中DateTime与DateTime2的区别

    DateTime字段类型对应的时间格式是 yyyy-MM-dd HH:mm:ss.fff ,3个f,精确到1毫秒(ms),示例 -- ::15.433 . DateTime2字段类型对应的时间格式是  ...

  9. Sql Server中charindex、patindex的区别

    SQL代码如下: select charindex('1,','121,1,1234') select patindex('%1,%','121,1,1234') ','121,1,1234') se ...

随机推荐

  1. C++ template —— 模板基础(一)

    <C++ Template>对Template各个方面进行了较为深度详细的解析,故而本系列博客按书本的各章顺序编排,并只作为简单的读书笔记,详细讲解请购买原版书籍(绝对物超所值).---- ...

  2. SpringMVC系列之URL匹配问题

    一.工程目录 二.web.xml配置文件及与其他文件的关系 三.控制器部分 四.返回值 五.url前后缀 六.项目源代码 http://files.cnblogs.com/files/xujian20 ...

  3. 【Java并发编程三】闭锁

    1.什么是闭锁? 闭锁(latch)是一种Synchronizer(Synchronizer:是一个对象,它根据本身的状态调节线程的控制流.常见类型的Synchronizer包括信号量.关卡和闭锁). ...

  4. Java单播、广播、多播(组播)

    一.通信方式分类 在当前的网络通信中有三种通信模式:单播.广播和多播(组播),其中多播出现时间最晚,同时具备单播和广播的优点. 单播:单台主机与单台主机之间的通信 广播:当台主机与网络中的所有主机通信 ...

  5. 【LeetCode OJ】Majority Element

    题目:Given an array of size n, find the majority element. The majority element is the element that app ...

  6. Oralce分析函数

    1 列传行  listagg(city,',')  within GROUP (order by city)    over (partition by nation) rank with temp ...

  7. 【Spring源码深度解析学习系列】复杂标签属性解析(四)

    一.创建用于属性承载的BeanDefinition BeanDefiniton是一个接口,在Spring中存在三种实现:RootBeanDefinition.ChildBeanDefinition.G ...

  8. Android 缓存策略demo

    packageinstaller\permission\model\PermissionApps.java /** * Class used to reduce the number of calls ...

  9. Clojure学习之defmulti

    1. defmulti 宏defmulti 和defmethod 经常被用在一起来定义 multimethod. 宏defmulti 的参数包括一个方法名以及一个dispatch函数,这个dispat ...

  10. oracle IMP-00085: 为无界导出文件指定了多个输入文件

    导入按表导出的数据的时候,提示为无界导出文件指定了多个输入文件 命令如下: imp user/user@database file=e:\test.dmp  提示信息: Import: Release ...