“覆盖索引使您能够避免返回到表中以满足请求的所有列,因为所有请求的列都已经存在于非聚集索引中。这意味着您还可以避免返回到表中进行任何逻辑或物理的信息读取。”

  然而,以上这不是我想要传达的全部意思,因为他不仅仅是避免逻辑或物理的读取的问题。在“非聚集索引”中的列和需要在表中查找的列之间,还需要考虑“将数据放在一起”的必要工作。为了说明这个问题,让我们创建两个完全一模一样的表,即:相同的结构,相同的数据且都是10000条:

CREATE TABLE Beach.dbo.cruiser_1
(
pkid INT IDENTITY(1,1) NOT NULL,
registration_id VARCHAR(20) NOT NULL,
last_name VARCHAR(50) NOT NULL,
first_name VARCHAR(50) NOT NULL,
address_1 VARCHAR(100) NULL,
address_2 VARCHAR(100) NULL,
city VARCHAR(100) NULL,
state_region VARCHAR(100) NULL,
postal_code VARCHAR(10) NULL,
company_id VARCHAR(20) NULL,
plus_one_notes VARCHAR(200) NULL,
registration_notes VARCHAR(200) NULL
); CREATE TABLE Beach.dbo.cruiser_2
(
pkid INT IDENTITY(1,1) NOT NULL,
registration_id VARCHAR(20) NOT NULL,
last_name VARCHAR(50) NOT NULL,
first_name VARCHAR(50) NOT NULL,
address_1 VARCHAR(100) NULL,
address_2 VARCHAR(100) NULL,
city VARCHAR(100) NULL,
state_region VARCHAR(100) NULL,
postal_code VARCHAR(10) NULL,
company_id VARCHAR(20) NULL,
plus_one_notes VARCHAR(200) NULL,
registration_notes VARCHAR(200) NULL
);

  请相信我,两个表中的数据是完全一样的。在此我们就暂时不把每个表10000条的数据展示了。同时,我已经在每个表上创建了完全一样的两个聚集索引,且都在pkid列上,

因为该列为自动增长列,我也把pkid列上的填充因子设置为了100%.

 ALTER TABLE dbo.cruiser_1 ADD CONSTRAINT
PK_cruiser_1_pkid PRIMARY KEY CLUSTERED
(
pkid
)
WITH
(
PAD_INDEX = OFF
, FILLFACTOR = 100
, STATISTICS_NORECOMPUTE = OFF
, IGNORE_DUP_KEY = OFF
, ALLOW_ROW_LOCKS = ON
, ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]; GO ALTER TABLE dbo.cruiser_2 ADD CONSTRAINT
PK_cruiser_1_pkid PRIMARY KEY CLUSTERED
(
pkid
)
WITH
(
PAD_INDEX = OFF
, FILLFACTOR = 100
, STATISTICS_NORECOMPUTE = OFF
, IGNORE_DUP_KEY = OFF
, ALLOW_ROW_LOCKS = ON
, ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]; GO

  最后,让我们在两个表之间引入一些不同的东西。dbo.cruiser_1是一个建立在 last_name和first_name列且具有包含列registration_id的非聚集索引.dbo.cruiser_2是与索引dbo.cruiser_1相同的非聚集索引但没有包含列,如下所示.

CREATE NONCLUSTERED INDEX [IX_cruiser_1_last_name] ON [dbo].[cruiser_1]
(
[last_name] ASC,
[first_name] ASC
)
INCLUDE
(
[registration_id]
)
WITH
(
PAD_INDEX = OFF
, STATISTICS_NORECOMPUTE = OFF
, SORT_IN_TEMPDB = OFF
, DROP_EXISTING = OFF
, ONLINE = OFF
, ALLOW_ROW_LOCKS = ON
, ALLOW_PAGE_LOCKS = ON
, FILLFACTOR = 80
)
GO CREATE NONCLUSTERED INDEX [IX_cruiser_2_last_name] ON [dbo].[cruiser_2]
(
[last_name] ASC,
[first_name] ASC
)
WITH
(
PAD_INDEX = OFF
, STATISTICS_NORECOMPUTE = OFF
, SORT_IN_TEMPDB = OFF
, DROP_EXISTING = OFF
, ONLINE = OFF
, ALLOW_ROW_LOCKS = ON
, ALLOW_PAGE_LOCKS = ON
, FILLFACTOR = 80
)
GO

  让我们重新回顾一下:我们有两个完全一样的table,每个表都有10000条记录。唯一的不同就是他们单一的非聚集索引,一个有包含列,另一个没有包含列。他们还有完全一样的主键及聚集索引。

  如果我在有包含列的表上提交以下的查询,我们会看到以下的执行计划:

  SELECT [registration_id], last_name, first_name 
  FROM Cruiser_1 
  WHERE last_name = 'Jones' AND first_name = 'Mary';
  

  上述操作都发生在非聚集索引的内部。我们也不需要回到表上获取更多的数据。如果我们执行完全一样的查询在具有同样索引结构的表上,在非聚集索引列除去了包含列,我们得到了不同的行为:

  SELECT [registration_id], last_name, first_name 
  FROM Cruiser_2 
  WHERE last_name = 'Jones' AND first_name = 'Mary';
  

  因为上述的非聚集索引并没有包含我们所需的所有信息来满足当前的查询,所以它有必要针对索引来获取基本信息,并且在非聚集索引上使用行指针,从表中获取registration_id并且运行一个嵌套循环,其目的是为了使两组工作数据在返回给终端用户之前结合在一起。针对上述查询,我们可以通过查看I/O统计来发现消耗在数据读取上不同的开销:

  请注意,这些都是逻辑读取,因为页面已经在缓冲区中。如果有这么一个情况,它是一个更大的数据集,如果你想要使用的页面仍然在活动服务器的磁盘上,这可能一个非常昂贵的操作。

  我希望上述操作能更好地描述了我的观点!  附:原文链接

SQL Server覆盖索引--有无包含列对数据库查询性能的影响分析的更多相关文章

  1. Sql Server 覆盖索引

    覆盖索引通常都是复合索引,即索引字段为多个.创建索引时应该注意索引排列顺序. Sql Server检索应用索引时,字段识别顺序为 从左到右. 例如如下索引的使用上 Create NONCLUSTERE ...

  2. SQL Server中多表连接时驱动顺序对性能的影响

    本文出处:http://www.cnblogs.com/wy123/p/7106861.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...

  3. SQL Server如何在变长列上存储索引

    这篇文章我想谈下SQL Server如何在变长列上存储索引.首先我们创建一个包含变长列的表,在上面定义主键,即在上面定义了聚集索引,然后往里面插入80000条记录: -- Create a new t ...

  4. SQL Server 2016新特性:列存储索引新特性

    SQL Server 2016新特性:列存储索引新特性 行存储表可以有一个可更新的列存储索引,之前非聚集的列存储索引是只读的. 非聚集的列存储索引支持筛选条件. 在内存优化表中可以有一个列存储索引,可 ...

  5. 【译】索引进阶(八):SQL SERVER唯一索引

    [译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正] 原文链接:传送门. 在本章节我们检查唯一索引.唯一索引的特别之处在于它不仅提供了性能益处,而且提供了数据完整性益处.在SQL SER ...

  6. SQL Server 查询优化 索引的结构与分类

    一.索引的结构 关系型数据库中以二维表来表达关系模型,表中的数据以页的形式存储在磁盘上,在SQL SERVER中,数据页是磁盘上8k的连续空间,那么,一个表的所有数据页在磁盘上是如何组织的呢?分两种情 ...

  7. SQL Server创建索引(转)

    什么是索引 拿汉语字典的目录页(索引)打比方:正如汉语字典中的汉字按页存放一样,SQL Server中的数据记录也是按页存放的,每页容量一般为4K .为了加快查找的速度,汉语字(词)典一般都有按拼音. ...

  8. 理解SQL Server中索引的概念

    T-SQL查询进阶--理解SQL Server中索引的概念,原理以及其他   简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能 ...

  9. SQL Server创建索引

    原文:SQL Server创建索引 什么是索引 拿汉语字典的目录页(索引)打比方:正如汉语字典中的汉字按页存放一样,SQL Server中的数据记录也是按页存放的,每页容量一般为4K .为了加快查找的 ...

随机推荐

  1. Linux wine

    一.简介 Wine是Wine Is Not an Emulator(Wine不是模拟器)的缩写,其实是一个转换层(或程序装入器),能够在Linux及与POSIX兼容的其他类似操作系统上运行Window ...

  2. Java进程与多线程+线程中的join、yield、wait等方法+synchronized同步锁使用

    首先了解什么是多线程与进程 进程:是一个执行过程,动态的概念 --->会分配内存线程:是进程的一个单元,线程是系统最小的执行单元 详解: http://blog.csdn.net/luoweif ...

  3. c++ 子类切勿重新定义父类 non-virtual函数

    子类如果重新定义了父类的non-virtual函数则不会有多态效果. 为方便描述,这里的方法和继承方式都用public.至于原因嘛,你懂的! 1:子类直接继承父类方法 class BaseOption ...

  4. CodeForces 658C Bear and Forgotten Tree 3 (构造)

    题意:构造出一个 n 个结点,直径为 m,高度为 h 的树. 析:先构造高度,然后再构造直径,都全了,多余的边放到叶子上,注意直径为1的情况. 代码如下: #pragma comment(linker ...

  5. WPF之MVVM模式(2)

    我们都想追求完美 Every view in the app has an empty codebehind file, except for the standard boilerplate cod ...

  6. .Net Core 使用Session

    1. NUGET包引用 icrosoft.AspNetCore.Session 2.Startup中添加一下代码: public void ConfigureServices(IServiceColl ...

  7. c++ 委托构造函数

    #include<iostream> ; using namespace std; class Cbox{ int a ; int b ; int c ; public: int g ; ...

  8. Tomcat 集群 + Redis Session 共享出现 Session 瞬间失效问题

    写在前面的话 写这篇博客出于公司最近要迁移到新的云上面且对之前的资源,架构做一个升级. 本来是一个不大的项目,旧环境旧一个 TOMCAT 跑起来,不过出于高可用考虑,新环境决定使用 TOMCAT 集群 ...

  9. 【探讨】linux环境,执行重启了php后php.ini依然不生效

    背景: 一个linux环境配置了多个php版本的环境,同时修改了多个php.ini,执行service php-fpm restart 之后,依然不生效 原因: 没有设置好启动php.ini 参考链接 ...

  10. 407. Trapping Rain Water II

    Given an m x n matrix of positive integers representing the height of each unit cell in a 2D elevati ...