SQL Server中SCAN 和SEEK的区别
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的区别的更多相关文章
- SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别
SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别 MSSQL为我们提供了两种动态执行SQL语句的命令,分别是 EXEC 和 SP_EXECUTESQL ,我们先来看一下两种方 ...
- [转]SQL SERVER中openrowset与opendatasource的区别
本文转自:http://blog.sina.com.cn/s/blog_6399df820102vyy8.html SQL SERVER中openrowset与opendatasource的区别: o ...
- SQL SERVER 中的smalldatetime和datetime区别
原文:SQL SERVER 中的smalldatetime和datetime区别 smalldatetime不能到秒. 不過它占的空間小.(4位) datetime(8位) 而且兩者的時間範圍不一樣. ...
- SQL Server中char与varchar数据类型区别
在SQL Server中char类型的长度是不可变的,而varchar的长度是可变的 . 存入数据时: 如果数据类型为char时,当定义一个字段固定长度时,如果存进去数据长度小于char的长度,那么存 ...
- SQL Server中Text和varchar(max) 区别
SQL Server 2005之后版本:请使用 varchar(max).nvarchar(max) 和 varbinary(max) 数据类型,而不要使用 text.ntext 和 image 数据 ...
- SQL Server中存储过程与函数的区别
本质上没区别.只是函数有如:只能返回一个变量的限制.而存储过程可以返回多个.而函数是可以嵌入在sql中使用的,可以在select中调用,而存储过程不行.执行的本质都一样. 函数限制比较多,比如不能用临 ...
- SQL Server中DELETE和TRUNCATE的区别
DELETE和TRUNCATE语句之间的区别是求职面试中最常见的问题之一.这两条语句都可以从表中删除数据.然而,也有不同之处. 本文将重点讨论这些差异,并通过实例加以说明. TRUNCATE DEL ...
- SQL Server中DateTime与DateTime2的区别
DateTime字段类型对应的时间格式是 yyyy-MM-dd HH:mm:ss.fff ,3个f,精确到1毫秒(ms),示例 -- ::15.433 . DateTime2字段类型对应的时间格式是 ...
- Sql Server中charindex、patindex的区别
SQL代码如下: select charindex('1,','121,1,1234') select patindex('%1,%','121,1,1234') ','121,1,1234') se ...
随机推荐
- 中文解码Unicode
package com.j1.search.utils; import java.io.UnsupportedEncodingException; import java.net.URLDecoder ...
- make clean、make mrproper、make distclean的区别【转】
本文转载自:http://blog.csdn.net/liyayao/article/details/6818061 内核编译时, 到底用make clean, make mrproper还是make ...
- windows之IP地址(一)
服务器: 顾名思义,是服务我们上网的机器.结构组成上和普通的PC结构相似,装了服务器版的系统后都可以作为服务器使用,但前者可靠性高.服务器是网络这个网上的中间节点,供每台终端进行访问.数据信息保存,有 ...
- C++多线程编程简单实例
C++本身并没有提供任何多线程机制,但是在windows下,我们可以调用SDK win32 api来编写多线程的程序,下面就此简单的讲一下: 创建线程的函数 HANDLE CreateThread( ...
- 《转载》Tomcat内存设置详解
原文地址:Java内存溢出详解 一.常见的Java内存溢出有以下三种: 1. java.lang.OutOfMemoryError: Java heap space ----JVM Heap(堆)溢出 ...
- <转>pandas学习
1.Pandas 基本介绍 Numpy 和 Pandas 有什么不同? 如果用 python 的列表和字典来作比较, 那么可以说 Numpy 是列表形式的,没有数值标签,而 Pandas 就是字典形式 ...
- Google Analytics访问空白的解决方法
在C:\Windows \System32 \drivers \etc下用记事本打开hosts文档 添加: 74.125.129.112 adwords.google.com 74.125.31.12 ...
- 如何区分slice、splice和split
小颖之前写过一篇文章:JavaScript Array 对象方法 以及 如何区分javascript中的toString().toLocaleString().valueOf()方法中有分享过slic ...
- [转]OpenStack Keystone V3
Keystone V3 Keystone 中主要涉及到如下几个概念:User.Tenant.Role.Token.下面对这几个概念进行简要说明. User:顾名思义就是使用服务的用户,可以是人.服务或 ...
- [Offer收割]编程练习赛13 B.最大子矩阵[枚举]
#1502 : 最大子矩阵 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个NxM的矩阵A和一个整数K,小Hi希望你能求出其中最大(元素数目最多)的子矩阵,并且该 ...