索引深入浅出(8/10):覆盖索引或列包含

在索引深入浅出:非聚集索引的B树结构在聚集表里,在聚集表里,我们看到非聚集索引的叶子层只包含非聚集索引键和聚集索引键。从聚集表结构或堆表结构里拿到剩下列,SQL Server需要进行书签/键查找操作。很多情况下书签或键查找非常消耗资源。我们来看个例子。

在这里我们打开了IO统计信息,还有点击工具栏的显示包含实际的执行计划。

 1 USE IndexDB
 2 GO
 3 DROP TABLE dbo.SalesOrderDetail                               
 4 GO                               
 5 SELECT * INTO dbo.SalesOrderDetail FROM AdventureWorks2008r2.Sales.SalesOrderDetail
 6 GO
 7 CREATE UNIQUE CLUSTERED INDEX ix_SalesOrderDetail ON dbo.SalesOrderDetail(SalesOrderDetailID)
 8 GO
 9 CREATE UNIQUE NONCLUSTERED INDEX ix_Productid ON dbo.SalesOrderDetail(ProductId,SalesOrderId)
10 GO 
11 SET STATISTICS IO ON
12 GO
13 SELECT SalesOrderDetailid,productid,salesorderid,orderqty,unitprice 
14 FROM SalesOrderDetail 
15 WHERE productid=707 AND SalesOrderID=43680

在IO统计信息里,SQL Server拿每条记录需要进行5个IO操作。在执行计划里,我们看到,查询开销的50%贡献给了书签查找(键查找)操作。

注意,这个表的非聚集索引有229个页,非聚集索引的B树结构深度为2。在这个非聚集索引里只要进行2个IO操作就可以完成查找操作,另外3个IO贡献给了书签查找。你可以用DBCC IND命令验证下或者参考下索引深入浅出(4/10):非聚集索引的B树结构在聚集表。

假设这个查询(用不同的参数)在应用程序里经常用到,现在你需要优化它。我们该怎么做?我们对此唯一能优化的话就是避免键查找(Key lookup)操作。因此我们修改下非聚集索引,把剩下2列(OrderQty, UnitPrice),不是聚集索引键,也不是非聚集索引键,也加入非聚集索引键。

1 DROP INDEX ix_Productid ON dbo.SalesOrderDetail
2 GO
3 CREATE UNIQUE NONCLUSTERED INDEX ix_Productid ON dbo.SalesOrderDetail(ProductId,SalesOrderId,OrderQty ,UnitPrice)
4 GO
5 SELECT SalesOrderDetailid,productid,salesorderid,orderqty,unitprice FROM SalesOrderDetail WHERE productid=707 AND SalesOrderID=43680 

从执行计划里我们可以看到,我们已经回避了键查找操作,把IO操作从5个降到了3次。但是我们如果用DBCC IND看下非聚集索引,我们发现由于还这个改动,我们的非聚集索引深度增加了。因为索引层的增加,非聚集索引需要进行3次IO来完成这个操作。这将是最糟糕的,如果选择列更多的话,我们就需要在非聚集索引里增加更多的列来避免键查找操作。

覆盖索引(covering index )就是用来解决这个问题的。覆盖索引帮助我们在非聚集索引的叶子层增加非主键列,最小可能增加B树结构的深度。可以用CREATE INDEX语句增加包含列完成。

当索引包含查询列是,这个为称为覆盖索引。当我们创建非聚集索引去覆盖一个查询时,我们可以在索引里包含非主键列来覆盖查询列,这些覆盖列在主查询列里不会用到。这样查询性能会提升,因为查询优化器在索引里就可以定位到需要列的数据,表或聚集索引不会被访问。

1 DROP INDEX ix_Productid ON dbo.SalesOrderDetail
2 GO
3 CREATE UNIQUE NONCLUSTERED INDEX ix_Productid ON dbo.SalesOrderDetail(ProductId,SalesOrderId) 
4 include(OrderQty ,UnitPrice)
5 GO
6 SELECT SalesOrderDetailid,productid,salesorderid,orderqty,unitprice FROM SalesOrderDetail 
7 WHERE productid=707 AND SalesOrderID=43680 

可以发现,我们已经避免了键查找操作,并把IO操作降到了2次。IO操作清楚的告诉我们聚集索引的深度是2。我们用DBCC IND和DBCC PAGE命令验证下。

 1 SELECT index_id FROM sys.indexes WHERE name='ix_Productid' AND OBJECT_ID= OBJECT_ID('SalesOrderDetail')
 2 GO
 3 DBCC ind('IndexDB','SalesOrderDetail',2) 
 4 
 5 TRUNCATE TABLE dbo.sp_table_pages
 6 INSERT INTO sp_table_pages EXEC('DBCC IND(IndexDB,SalesOrderDetail,2)')
 7 GO
 8 
 9 SELECT * FROM dbo.sp_table_pages ORDER BY IndexLevel DESC --根节点/索引页
10 
11 DBCC TRACEON(3604)
12 DBCC PAGE(IndexDB,1,2800,3)--根页
13 
14 DBCC TRACEON(3604)
15 DBCC PAGE(IndexDB,1,2736,3)--叶子页

include语句提到的列已经加到了叶子层的页,没有对非页层页造成影响。
列包含非常有用,我们可以把不能在索引键里加的列,在列包含里加入。另外避免超过当前索引大小的限制(最大键列数为 16,最大索引键大小为 900 字节)。我们可以包含除去text,ntext和image类型的其他列,列包含也同样支持计算列(computed column)。

参考文章: 

http://www.sqlservercentral.com/blogs/practicalsqldba/2013/03/25/sql-server-part-8-explaining-the-covering-index-or-included-columns/

转载于:https://www.cnblogs.com/woodytu/p/4509673.html

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

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

相关文章

靶场练习第二十三天~vulnhub靶场之GOATSELINUX: 1

一、准备工作 kali和靶机都选择NAT模式(kali与靶机同网段) 1.靶场环境 下载链接:GoatseLinux: 1 ~ VulnHub 2.kali的ip 命令:ifconfig 3.靶机的ip 扫描靶机ip sudo arp-scan -l 二、信息收集 1.nmap的信息收集 (1)扫描靶机…

Spring事务报Connection is read-only

昨天做项目时,写了个方法,程序突然报了Connection is readonly. Queries leading to data modification are not allowed调了程序半天,最后才发现是自己在spring配置文件中增加了事务.把方法写成了大写开头了,但是spring配置是以小写开头 代码…

HTTP协议具体解释

HTTP是一个属于应用层的面向对象的协议。因为其简捷、高速的方式。适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完好和扩展。眼下在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工作正在进行之中&#x…

靶场练习第二十四天~vulnhub靶场之Raven-1

一、准备工作 kali和靶机都选择NAT模式(kali与靶机同网段) 1.靶场环境 下载链接:Raven: 1 ~ VulnHub 2.kali的ip 命令:ifconfig 3.靶机的ip 扫描靶机ip sudo arp-scan -l 二、信息收集 1.nmap的信息收集 (1)扫描靶机开放的…

【知识积累】DES算法之C#加密Java解密

一、前言 在项目需要添加安全模块,客户端调用服务端发布的service必须要经过验证,加密算法采用DES,客户端采用C#进行加密,服务端使用Java进行解密。废话不多说,直接上代码。 二、客户端 客户端采用C#进行开发&#xff…

Space.js – HTML 驱动的页面 3D 滚动效果

为了让我们的信息能够有效地沟通,我们需要创建用户和我们的媒体之间的强有力的联系。今天我们就来探讨在网络上呈现故事的新方法,并为此创造了一个开源和免费使用的 JavaScript 库称为 space.js。该库是 HTML 驱动的,这意味着你不需要在网站上…

离职感言-Symbio的5年工作回顾和总结(转载)

离职感言-Symbio的5年工作回顾和总结 (2011-06-02 21:06:30) 转载▼2005年底,当时我在西安过的还不错,结了婚,买了房,在公司也受老板器重,但是初为人父,孩子带给我的那种人生紧迫感:“再不趁还…

64位CentOS6.2安装erlang及rabbitmqServer

CentOS 6.2 64bit 安装erlang及RabbitMQ Server 1、操作系统环境(CentOS 6.2 64bit) 1 [rootHAproxy ~]# cat /etc/issue2 3 CentOS release 6.2 (Final)4 Kernel \r on an \m5 [rootHAproxy ~]# cat /proc/cpuinfo |grep "clflush size"6 clflush size : 647 clf…

Kafka的Producer和Consumer源码学习

先解释下两个概念: high watermark (HW) 它表示已经被commited的最后一个message offset(所谓commited, 应该是ISR中所有replica都已写入),HW以下的消息都已被ISR中各个replica同步,从而保持一致。HW以上的消息可能是脏数据:部分r…

for+next()实现数组的遍历及while list each 的使用

//要求使用for循环语句来完成该数组的遍历//输出每一项的键名和对应值&#xff1a; $a array( a > 34, 5 > 51, 13, 32, bb>15, 2 > 31 ); $len count($a); for($i0;$i<$len;$i)…

读Pyqt4教程,带你入门Pyqt4 _005

对话框窗体或对话框是现代GUI应用不可或缺的一部分。dialog定义为两个或多个人之间的交谈。在计算机程序中dialog是一个窗体&#xff0c;用来和程序“交谈”。对话框用来输入数据、修改数据、改变程序设置等等。对话框是用户和计算机程序沟通的重要手段。 QColorDialog 颜色对话…

Linux内核的启动过程分析

秦鼎涛 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000  一、实验目的及要求&#xff1a; 使用gdb跟踪调试内核从start_kernel到init进程启动 详细分析从start_kernel到init进程启动的过程并结合实验截图撰写一篇署名博客&#xff0c;并在博客文…

static修饰符详解

static表示“全局”或者“静态”的意思&#xff0c;用来修饰成员变量和成员方法&#xff0c;也可以形成静态static代码块&#xff0c;但是Java语言中没有全局变量的概念。被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说&#xff0c;它不依赖类特定的实例&…

四则运算2+psp0

程序要求&#xff1a; 1.题目避免重复 2.可定制&#xff08;数量\打印方式&#xff09; 3.可以一下控制参数 ① 是否有乘除法 ② 是否有括号&#xff08;最多支持十个数参与运算&#xff09; ③ 数值范围 ④加减有无负数 ⑤除法有无余数 分析&#xff1a;① 如果是两个数…

kettle作业中的js如何写日志文件

在kettle作业中JavaScript脚本有时候也扮演非常重要的角色&#xff0c;此时我们希望有一些日志记录。下面是job中JavaScript记录日志的方式。 job的js写日志的方法。 得到日志输出实例 org.pentaho.di.core.logging.LogWriter.getInstance();按照日志的级别输出&#xff1a; pu…

浅析Kerberos原理,及其应用和管理

文章作者&#xff1a;luxianghao 文章来源&#xff1a;http://www.cnblogs.com/luxianghao/p/5269739.html 转载请注明&#xff0c;谢谢合作。 免责声明&#xff1a;文章内容仅代表个人观点&#xff0c;如有不当&#xff0c;欢迎指正。 --- 一&#xff0c;引言 Kerberos简单来…

2014! 的末尾有多少个0

2014&#xff01; 的末尾有多少个0<?xml version"1.0" encoding"UTF-8"?> 假设 末尾有 k 个0&#xff0c;所以 2014&#xff01; x * 10^k ; 10 ^ k &#xff08;2 * 5 &#xff09;^ k 2^k * 5^k, 明显所有数字中因数含有2的数字多于含有5的数…

[转载]一句话插配置文件

http://www.t00ls.net/viewthread.php?tid13901 一句话插入配置文件system.asp没有过滤双引号&#xff0c;插入一句就行。常规插法如下&#xff1a;"%><%eval request("d")%><%但金刀客这篇文件&#xff08;http://www.cqzh.cn/post/328.html&…

android插件化-获取apkplug框架已安装插件-03

上一篇文章成功的将apkplug框架嵌入了应用中而且启动 链接http://www.apkplug.com/blog/?post10 这一篇文章实现怎样获取全部已安装插件 一 获取框架的SystemBundle的上下文BundleContext apkplug框架启动会自己主动创建一个SystemBundle, 它是框架的第一个插件不可停止和卸…

Java实现栈。

定义一个接口MyStack接口&#xff1a; package Stack; public interface MyStack<T> { boolean isEmpty(); int length(); boolean push(T date); T pop();} 数组实现&#xff1a; package Stack; public class ArrayStack<T> implements MyStack<T>{ privat…