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这两种查找方式和堆表,聚簇索引和非聚簇索引的各种组合:

       ScanSeek
HeapTable Scan 
Clustered IndexClustered Index ScanClustered Index Seek
Non-Clustered IndexIndex ScanIndex 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,可以每次只重新编译存储过程的一部分(当然,你也可以选择重新编译整个存储过程,这取决于你的需求。详见联机文档。)

 

转载于:https://www.cnblogs.com/gered/p/8780177.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/398324.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HDU 2897 (博弈 找规律) 邂逅明下

根据博弈论的两条规则&#xff1a; 一个状态是必胜状态当且仅当有一个后继是必败状态一个状态是必败状态当且仅当所有后继都是必胜状态然后很容易发现从1开始&#xff0c;前p个状态是必败状态&#xff0c;后面q个状态是必胜状态&#xff0c;然后循环往复。 1 #include <cstd…

C# 设置Excel打印选项及打印excel文档

C# 设置Excel打印选项及打印excel文档 打印Excel文档是一个很常见的操作&#xff0c;但有时候我们会碰到各种不同的打印需求&#xff0c;例如只打印一个Excel工作表的其中一部分&#xff0c;或打印时每页都有表头&#xff0c;或把工作表中超出1页所有内容打印到1页上等等&#…

tp5框架原理详解_笔记:TP5框架完整学习笔记

安装配置官网下载TP5完整版(初学者学习用的)解压到本地的开发环境phpstudy中&#xff0c;默认的入口文件是public&#xff0c;访问public会看到TP5成功页面。目录介绍一般开发中&#xff0c;代码都是写在application这个文件夹中开发一个项目的时候&#xff0c;通常分为前台和后…

mustache 模板使用

//一 ,基本使用 <!DOCTYPE html><html ng-app"myApp"><head lang"en"> <meta charset"UTF-8"> <title></title> <script src"jquery-1.10.2.min.js"></script> <script src"…

Sphinx编译docs文档

在使用Python、Django的过程中&#xff0c;经常看到docs目录&#xff0c;里面存放着一些txt文本文件&#xff0c;也就是自带的一些帮助文档&#xff0c;里面有make.bat&#xff0c;在dos目录下直接执行make&#xff0c;给出的帮助是可以转换成Html、PDF等文件形式&#xff0c;那…

js传参不是数字_js调用函数时传入的参数个数与函数定义时的参数个数不符时的操作...

1.在js中函数没有重载的概念&#xff0c;如果声明了多个重名的函数&#xff0c;不管函数的形参个数是否一样&#xff0c;只有最有一个有效&#xff0c;其他的函数声明都是无效的。比如说声明了两个函数fn()&#xff0c;第一次声明时没有形参&#xff0c;第二次声明时形参有两个…

精妙SQL语句收集(转)

SQL语句先前写的时候&#xff0c;很容易把一些特殊的用法忘记&#xff0c;我特此整理了一下SQL语句操作。 一、基础 1、说明&#xff1a;创建数据库 CREATE DATABASE database-name 2、说明&#xff1a;删除数据库 drop database dbname 3、说明&#xff1a;备份sql serv…

原生JS字符串操作方法汇总

1.转换为字符串类型(三种实现方式) 1 var num110; 2 var mystrnum.toString(); //"110" 3 4 var num111; 5 var mystrString(num); //"111" 6 7 var num112; 8 var mystr"" num; //"112" 2.字符串分割返回新的数…

解决问题:修改tomcat启动后服务器url

解决问题&#xff1a;修改tomcat启动后服务器url 解决方式&#xff1a;通过在pom.xml配置文件中使用configuration标签的子标签path可以修改http://localhost:8080后跟什么路径。如path标签中为/&#xff0c;则tomcat启动后服务器url为http://localhost:8080/

用js来实现那些数据结构 第一章

在开始正式的内容之前&#xff0c;不得不说说js中的数据类型和数据结构&#xff0c;以及一些比较容易让人混淆的概念。那么为什么要从数组说起&#xff1f;数组在js中是最常见的内存数据结构&#xff0c;数组数据结构在js中拥有很多的方法&#xff0c;很多初学者记不清数组的大…

excel密码忘记了怎么办

2019独角兽企业重金招聘Python工程师标准>>> Excel电子表格应用程序堪称Office中的“王牌应用”&#xff0c;能够快速灵活地整理各种大数据&#xff0c;在各行各业中发挥着不可替代的作用。因此&#xff0c;excel文档的跋扈密码比其他文档多&#xff0c;除了常设的打…

关于Android定制Launcher

好久没有做Adroid项目开发了&#xff0c;临时需要开发一个APK. 客户要求该APK作为launcher存在&#xff0c;折腾了一些时间&#xff0c;特此记录以免忘了。 按照网络上的要求&#xff0c;添加 <category android:name"android.intent.category.DEFAULT" /> …

Android2.2 API 中文文档系列(3) —— AccessibilityService

前言 关键字&#xff1a; Android API 中文,Android SDK 中文,Android AccessibilityService 详解 本章翻译来自 java_cofi &#xff0c;他的博客地址&#xff1a;http://java-cofi.javaeye.com/admin&#xff0c;这里本博负责整理和发布&#xff0c;欢迎其他译者一起参与Andro…

rest风格使用两个变量_为什么要用Rest风格,接口应该怎么定义,除了Rest还可用什么方式写接口的?...

这里是修真院后端小课堂&#xff0c;每篇分享文从深度思考中的知识点——为什么要用Rest风格&#xff0c;如果不用Rest的话&#xff0c;接口应该怎么定义&#xff0c;在使用Rest风格之前&#xff0c;大家都是用什么方式写接口的&#xff1f;1.背景介绍REST(Representational St…

Smobiler 4.4 更新预告 Part 1(Smobiler能让你在Visual Studio上开发APP)

在4.4版本中&#xff0c;大家对产品优化的一些建议和意见进行了相应的优化和修复&#xff0c;同时&#xff0c;还新增了一些令人激动的功能和插件。 下面先为大家介绍4.4版本中Smobiler的优化和修复&#xff1a; 优化 1&#xff0c; PageView的AutoPlay默认属性改为True。 2&am…

cad lisp 二次抛物线_学习CAD的五个段位,你是青铜还是王者?

大家学习AutoCAD多久了&#xff0c;从入门到精(fang)通(qi)&#xff0c;小编总结了5个段位&#xff0c;大家对号入座。此时视口内的三维实体并没有任何变化&#xff0c;需要后续使用soldraw才能进行转换。SOLVIEW创建的视口经过SOLDRAW处理后&#xff0c;会生成表示实体轮廓和边…

Python 基础知识(二)

一、基础数据类型 1、数字int 数字主要是用于计算用的&#xff0c;使用方法并不是很多&#xff0c;就记住一种就可以&#xff1a; #bit_length() 当十进制用二进制表示时&#xff0c;最少使用的位数 # -*- coding:UTF-8 -*- v 11 data v.bit_length() print(data) # 二进制&a…

深入理解JavaWeb(五)——过滤器和监听器

深入理解JavaWeb&#xff08;五&#xff09;——过滤器和监听器 摘要&#xff1a;在基于Java-Web核心技术的开发应用中&#xff0c;为了一些特定的用途或目的&#xff0c;那么Filter和Listener就要闪亮登场了。在本文中我们来聊一聊Servlet规范中的另俩技术的核心知识点&#x…

G - 娜娜梦游仙境系列——梦醒

G - 娜娜梦游仙境系列——梦醒 Time Limit:2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Special JudgeProblem Description 娜娜离开了这个王国&#xff0c;走向远方&#xff0c;在旷野上&#xff0c;娜娜看到了一个大时钟&#xff0c;上面的…

DB2 常用操作命令集合

1、 打开命令行窗口 #db2cmd 2、 打开控制中心 # db2cmd db2cc 3、 打开命令编辑器 db2cmd db2ce 操作数据库命令 4、 启动数据库实例 #db2start 5、 停止数据库实例 #db2stop 如果你不能停止数据库由于激活的连接&#xff0c;在运行db2stop前执行db2 force applica…