索引的访问-SQL Server

全表扫描

无序扫描

表扫描/无序聚集索引扫描

表扫描或无序聚集索引扫描都连续地扫描表中的所有数据页。

表扫描

在堆上进行无序全表扫描称为表扫描

例如,Order表按堆结构组织(没有聚集索引),执行如下查询:

SELECT orderid, custid, empid, shipperid, orderdate FROM  Orders;

SQL Server将根据该表的IAM页指示磁臂按物理顺序扫描属于该表的区,逻辑读取数等于该表所包含的页数。但是在这种扫描中,SQL Server通常使用非常高效的预读策略(针对连续I/O),利用该策略可以在大于8 KB(页)的大块(区)中读取数据,因此实际读取数会小于该表所包含的页数。

无序聚集索引扫描

在聚集表上进行无序全表扫描称为无序聚集索引扫描。尽管表上有聚集索引,SQL Server仍然使用聚集索引(聚集表)的IAM页来连续地扫描数据,这就意味着该访问方法并不依赖于维护聚集索引逻辑顺序的链接列表,而是按聚集索引叶级页在磁盘上的物理顺序进行。

因为该操作与表扫描没有什么不同,所以统称表扫描。

无序覆盖非聚聚索引扫描

无序覆盖非聚聚索引扫描概念类似于无序聚集索引扫描。覆盖索引表示非聚集索引(索引列)包含查询中的所有列。换句话所,覆盖索引不是一个具有特殊属性的索引,而是关于特定查询的覆盖索引。SQL Server只访问索引数据(非聚集索引叶级页)就可以找到满足查询所需要的全部数据,而不用访问完整的数据行。另一方面,该访问方法与无序聚集索引扫描相同,只不过覆盖非聚集索引的叶级比聚集索引的叶级包含的页要少,因此行的大小更小(只包含索引列),每个页可以容纳更多的行。

例如,Order表在orderid列上具有非聚集索引,这就意味着该表的所有orderid (订单ID)都位于非聚集索引的叶级上,也就是说非聚集索引覆盖了上面的查询。执行如下查询:

SELECT orderid FROM  Orders;

SQL Server使用非聚集索引的IAM页来连续扫描非聚集索引的叶级页,按照非聚集索引的叶级页在磁盘中的物理顺序进行访问。

有序扫描

有序聚集索引扫描

有序聚集索引扫描是按链接列表对聚集索引叶级执行的完整扫描。

例如,Order表在orderid列上具有聚集索引,执行如下查询:

SELECT orderid, custid, empid, shipperid, orderdate

FROM Orders

ORDER BY orderdate;

不同于无序索引扫描,有序扫描的性能取决于索引的碎片级别。也就是说,索引叶级别中无序页占总页数的百分比。无序页是指,根据链接表逻辑上出现在一页后面,但物理上却在其前面的。对于没有碎片的索引,有序索引扫描的性能接近于无序扫描,因为两者都是连续地读取物理上的数据。然而,随着碎片级别越来越高,他们性能差异就越来越显著。当然,无序扫描性能更高。

有序覆盖非聚集索引扫描

有序覆盖非聚集索引扫描概念上类似于有序聚集索引扫描,只不过前者只需要访问非聚集索引叶级页。因为只涉及更少的页,它的成本肯定比聚集索引扫描低。

例如,Order表在orderid列上具有非聚集索引,并且非聚集索引覆盖了我们的查询,执行如下查询:

SELECT orderid FROM Orders ORDER BY orderid;

局部扫描

有序扫描

非聚集索引查找+有序局部扫描+lookups

这种访问方式通常用于小范围查询(包括点查询),且用到的非聚集索引没有覆盖该查询。

第一步,在非聚集索引内执行查找以定位被查询范围的第一个键(orderid=101)。

第二步,从该范围内的第一个键开始在叶级别执行有序局部扫描,直到找到最后一个键。

第三步,为找的每个键查找(lookup)对应的数据行。

注意第三步不需要等到第二步执行完。对于该范围内找到的每个键都应用lookup,在堆中执行lookup只需读取一页,而聚集表中执行lookup所读取的页数等于聚集索引的级数。

这种访问方法中,第三步lookup操作通常会占查询成本的一大部分,因为它涉及大量的I/O,理解这一点对评估性能很重要。Lookup为每个找到的键在堆中读取一页或在聚集索引中执行完整的查找(seek),而且lookup总是随机的I/O(不是连续I/O)。

要估算这种查询的I/O成本,你通常可以重点关注lookups的成本,如果你想要更精确的估计I/O成本,还可以考虑对非聚集索引的查找和有序局部扫描。不过随着范围越来越大,这部分的成本可以忽略不计。一次非聚集索引的查找操作的成本大约是3(非聚集索引的级数)次逻辑读取。有序局部扫描的I/O成本取决于该范围内的行数和非聚集索引叶级页可容纳的行数。一般局部扫描实际上并不包含额外的读取,因为我们查找范围内的所有键一般都位于查找操作所到达的叶级页,或者在连接列表随后的一页或多页。Lookups操作的I/O成本等于该范围内的行数乘以一次lookup的成本。对于堆上的lookup,成本为一次逻辑读取。对于聚集表上的lookup,逻辑读取数为聚集索引的级数。由于在聚集表中的所有的lookup操作都会查询聚集索引的非叶级,聚集索引的非叶级通常位于缓存,所以你不用过于担心在聚集表中进行lookup表面上的高成本。

在堆上应用

例如,Orders表(按堆组织)在orderid列上具有非聚集索引,但是该索引没有覆盖如下查询。

SELECT orderid, custid, empid, shipperid, orderdate

FROM Orders

WHERE  orderid BETWEEN 101 AND 120;

在聚集表上应用

例如,Orders表在orderid列上具有聚集索引,在orderdate列上具有非聚集索引,表中没有覆盖该查询的索引。

SELECT orderid, custid, empid, shipperid, orderdate

FROM Orders

WHERE  orderdate >= ‘20060101‘ AND orderdate < ‘20070101‘;

聚集索引查找+有序局部扫描

对于按聚集索引的第一个键列进行筛选的范围查询,采用这种访问方法。这种方法先执行查找操作(seek)找到该范围内的第一个键,然后在聚集索引叶级应用局部扫描,从第一个键扫描到最后一个键。这种方法主要好处是它不涉及lookups。对于较大的范围,lookups的成本非常高,随着范围的越来越大,不涉及lookups的访问方法和使用非聚集索引及lookups的访问方法在性能方面差异会越来越大。

例如,表Orders在(orderdate,orderid)上具有聚集索引。执行如下查询:

SELECT orderid, custid, empid, shipperid, orderdate

FROM Orders

WHERE orderdate = ‘20060212‘;

虽然筛选器使用了等于运算符,但它本质上还是一个范围查找,因为表中存在多个符合条件的行,点查询也可以被看作是范围查询的一个特例。这种访问方法的成本包括在聚集索引上的查找成本(聚集索引级数)和聚集索引叶级页内有序局部扫描的成本。

有序扫描通常占查询成本的大部分,因为它涉及大部分的I/O。对于有序索引扫描,索引碎片具有至关重要的作用。当碎片处于最低级别,物理读取几乎是连续的。不过随着碎片级别不断增大,磁臂必须疯狂地来回移动,从而严重降低扫描的性能。

覆盖非聚集索引查找+有序局部扫描

覆盖非聚集索引查找+有序局部扫描这种访问方法几乎与上一个访问方法相同,唯一的区别是前者使用覆盖非聚集索引,而不是聚集索引。要使用这种方法,被筛选列必须是索引的第一个键列。相对于上一个方法,这个访问方法的好处是在于非聚集索引的一个叶级页可以比聚集索引的一个页级页容纳更多的行,因此该访问方法的大部分成本,即叶级的局部扫描成本显得更低,即在相同范围内,被扫描的页更少,当然索引碎片也对性能有重要的影响,因为局部扫描是有序的。

例如,表Orders在(custid,orderdate)具有非聚集索引,并且该聚集索引覆盖了如下查询。

SELECT  orderdate, custid

FROM Orders

WHERE custid= ‘C0000000001‘ AND orderdate >= ‘20060101‘ AND orderdate < ‘20070101‘;

无序扫描

无序非聚集索引扫描+lookups

适用条件:

1、该查询的选择性足够高。选择性被定义为查询返回的行占表中总行数的百分比。

2、非聚集索引没有按顺序维护被查找的键。例如,当你筛选的列不是非聚集索引的第一个键列时就属于这种情况。

该访问方法将对索引叶级执行无序的完全扫描,然后再执行一系列的lookups。查询的选择性必须足够高才能适用这种访问方法,否则,太多的lookup会使得该方法访问成本比直接扫描整个表还高。要计算查询的选择性,SQL
Server需要有被筛选列的统计信息(包含值分布的直方图)。

该查询的成本包括对非聚集索引的无序扫描(使用IAM页的连续I/O)成本和lookups成本(随机I/O)。扫描所非聚集索引的页数等于非聚集索引叶级的页数。lookups的成本等于符合条件的行数乘以一次lookup的成本。在对上lookup成本为1次页读取,在聚集表上,逻辑读取数为聚集索引的级数。

在堆上的应用

例如,表Order上具有非聚集索引(orderdate ,custid),其中custid不是非聚集索引中的第一个键列。执行如下查询:

SELECT orderid, custid, empid, shipperid, orderdate  FROM Orders WHERE custid = ‘C0000000001‘;

在聚集表上的应用

例如,表Order上具有非聚集索引(orderdate ,custid),其中custid不是非聚集索引中的第一个键列,此外表Order在列orderid上有聚集索引。执行如下查询:

SELECT orderid, custid, empid, shipperid, orderdate  FROM Orders WHERE custid = ‘C0000000001‘;

时间: 2024-10-11 06:21:01

索引的访问-SQL Server的相关文章

SQL Server索引简介:SQL Server索引级别1

作者David Durant,2014/11/05(第一版:2011/02/17) 原文链接: http://www.sqlservercentral.com/articles/Stairway+Series/72284/ 该系列 本文是"Stairway系列:SQL Server索引的阶梯"的一部分 索引是数据库设计的基础,并告诉开发人员使用数据库关于设计者的意图.不幸的是,当性能问题出现时,索引往往被添加为事后考虑.这里最后是一个简单的系列文章,应该使他们快速地使任何数据库专业人员

[翻译]——SQL Server索引的介绍:SQL Server索引级的阶梯

SQL Server索引的介绍:SQL Server索引级的阶梯 By David Durant, 2014/11/05 (first published: 2011/02/17) 该系列 本文是楼梯系列的一部分:SQL Server索引的阶梯 索引是数据库设计的基础,并告诉开发人员使用数据库非常了解设计器的意图.不幸的是,当性能问题出现时,索引常常被添加到事后.这里最后是一个简单的系列文章,它应该能让任何数据库专业人员快速"跟上"他们的步伐 第一个层次引入了SQL Server索引:

聚集索引: 三级阶梯SQL Server索引

原文链接:http://www.sqlservercentral.com/articles/Stairway+Series/72351/   聚集索引:三级阶梯SQL Server索引 通过大卫·杜兰特,2013/01/25(第一次出版:2011/06/22) 该系列 本文是楼梯系列的一部分:SQL Server的阶梯索引 索引数据库设计的基础,告诉开发人员使用数据库设计者的意图. 不幸的是索引时往往是后加上的性能问题出现. 终于在这里是一个简单的系列文章,应该让任何数据库专业迅速"加速&quo

SQL Server索引内部结构:SQL Server索引的阶梯级别10

作者David Durant,2012年1月20日 该系列 本文是"Stairway系列:SQL Server索引的阶梯"的一部分 索引是数据库设计的基础,并告诉开发人员使用数据库关于设计者的意图.不幸的是,当性能问题出现时,索引往往被添加为事后考虑.这里最后是一个简单的系列文章,应该使他们快速地使任何数据库专业人员"快速" 在之前的水平上,我们采取了合理的方法来指标,重点是他们能为我们做些什么.现在是时候采取物理方法,检查指标的内部结构;了解索引的内部特性导致了对

.NET跨平台之旅:升级至ASP.NET 5 RC1,Linux上访问SQL Server数据库

今天微软正式发布了ASP.NET 5 RC1(详见Announcing ASP.NET 5 Release Candidate 1),.NET跨平台迈出了关键一步. 紧跟这次RC1的发布,我们成功地将运行在Linux上的示例站点(http://about.cnblogs.com)升级到了ASP.NET 5 RC1,并且增加了数据库访问功能——基于Entity Framework 7 RC1访问SQL Server数据库. 示例站点页面左侧的导航是从数据库读取数据动态加载的,数据库服务器用的是阿里

NodeJS下访问SQL Server

1.下载node-sqlserver(msnodesql-0.2.1-v0.8-x64.msi) msnodesql 下载地址:下载  自行选择与自己系统相符的版本,点击安装. msnodesql 官方地址:https://github.com/WindowsAzure/node-sqlserver 含wiki 和 疑问解答 . 2.打开msnodesql 文件夹下的README.md文件,里面有说到要安装的东西. 3.安装node-gyp,打开命令行,输入命令: npm install -g

访问SQL Server WMI对象

访问SQL Server WMI对象 1. 使用Powershell访问 get-wmiobject -list -namespace "root\Microsoft\SqlServer" get-wmiobject -list -namespace "root\Microsoft\SqlServer\ServerEvents\MSSQLSERVER" get-wmiobject -namespace "root\Microsoft\SqlServer\C

Oracle Gateways透明网关访问SQL Server

自己的本机安装了Oracle 12c,公司的平台需要同时支持Oracle与SQL Server,很多时候都有将数据从Oracle同步到SQL Server的需求.通过SQL Server的link Server可以达到目的,但是因为SQL Server都是64位版本,试过很多次都失败了.再安装32位SQL Server也懒得折腾.因Oracle是12c, 安装的Gateways也是12c.尝试过在Oracle数据库服务器(本机)安装11g的gateways, 但是配置都失败了.    Oracl

Ubuntu12.10下Python(pyodbc)访问SQL Server解决方案

一.基本原理 请查看这个网址,讲得灰常详细:http://www.jeffkit.info/2010/01/476/ 二.实现步骤 1.安装linux下SQL Server的驱动程序 安装Freetds,不要使用apt-get install 来安装,因为源里的版本不一定是新的,建议使用stable版本, 下载源码手工编译安装,因为有好些参数需要在编译中指定的. 执行以下命令: tar zfvx freetds-stable.tgz cd freetds-* ./configure --pref