SQL Server索引入门:SQL Server索引1级的阶梯
David Durant,2014 / 11 / 05
该系列
索引是数据库设计的基础,并告诉开发人员使用数据库大量关于设计者的意图。不幸的是,当性能问题出现时,索引常常会作为事后考虑添加。这里最后是一系列简单的文章,应该能让数据库专业人员快速地与它们同步。
第一级引入SQL Server索引:使SQL Server能够在最少的时间内查找和/或修改所请求的数据的数据库对象,使用最少的系统资源实现最大性能。好的索引还允许SQL Server实现最大并发性,这样由一个用户运行的查询对其他人运行的查询几乎没有影响。最后,索引提供了一种有效的方法来强制数据完整性,通过确保创建惟一索引时键值的唯一性。这个级别是一个介绍,它涵盖了概念和用法,但是将物理细节留给了后面的层次。
对索引的透彻理解对于数据库开发人员来说是非常重要的,原因之一是:当对SQL Server的请求从客户机到达时,SQLServer只有两种可能的方法访问请求的行:
它可以扫描包含数据的表中的每一行,从第一行开始,一直持续到最后一行,检查每一行是否符合请求标准。
或者,如果可用索引可用,则可以使用索引查找所请求的数据。
SQL服务器总是可以使用第一个选项。如果您已经指示SQL Server创建一个有益的索引,那么第二个选项是可用的,但它可以导致显著的性能改进,我们将在后面的这个级别上说明。
因为索引具有与它们相关联的开销(它们占用空间并且必须与表保持同步),所以它们不需要SQL Server。有一个没有索引的数据库是可能的。它可能执行得很差,它肯定会有数据完整性问题,但SQL Server会允许它。
然而,这不是我们想要的。我们都需要一个性能良好、具有数据完整性的数据库,同时将索引开销控制到最低限度。这个水平将使我们朝着那个目标前进。
示例数据库
在整个楼梯中,我们将用例子来说明关键的概念。这些例子都是基于微软的AdventureWorks示例数据库。我们专注于销售订单功能。表五将给我们一个很好的组合交易与非交易数据;客户、销售人员、产品、salesorderheader,和salesorderdetail。为了使事情集中,我们使用列的一个子集。
AdventureWorks是归一化,所以销售人员的信息分为三台;销售人员,员工和接触。对于一些示例,我们将把它们当作一个单独的表对待。我们将使用的完整的表集以及它们之间的关系,如图1.1所示。
图1.1:将被用在这楼梯AdventureWorks表
注:
所有的TSQL代码在这个楼梯水平显示可以下载与文章(见本文末尾的链接)
什么是索引?
我们开始用一个简短的故事来研究索引,一个使用旧的但经过验证的技术,我们将在本文中介绍索引的基本概念。
你离开家去办几件事。当你回来时,你会发现女儿的垒球教练在等你。三个女孩,特雷西,丽贝卡和艾米都输了他们的团体帽。请你去运动用品商店买帽子给女孩子好吗?。他们的父母会在下一场比赛中补偿你。
你认识这些女孩,你知道他们的父母。但你不知道他们的帽子尺寸。你镇上的某个地方有三间住宅,每个住宅都有你需要的信息。没问题,你只要打电话给父母拿帽子大小就行了。你伸手去拿你的电话,你就可以找到一个索引——电话簿的白页。
你需要到达的第一个居住地是Helen Meyer。估计“迈耶”将位于附近的人群中间,你跳到白色的页面中;才发现你是在页面的标题说“Kline Koerber”。你让一个较小的跳跃前进到“Nagle Nyeong”的页面。一个更小的向后跳可以让你在“Maldonado Nagle”的页面。意识到您现在在正确的页面上,您可以扫描页面,直到您到达“迈耶、海伦”行并获取电话号码。使用电话号码,您到达迈耶住所,并获得您需要的信息。
你再重复两次,到达另外两个住宅,再获得两个帽子尺寸。
您刚刚使用了一个索引,而且它的使用方式与SQL Server使用索引的方式大致相同,因为在白页和SQLServer索引之间有很大的相似之处和一些差异。
事实上,你只是用指数代表一个类型的SQL Server的SQL Server支持两个指标:聚集和非聚集。白色的页面的最佳代表非聚集索引的概念。因此,在这个层面我们引入非聚集索引。随后的级别将引入聚集索引,并进一步深入到这两种类型中。
非聚集索引
白色的页面是类似于一个非聚集索引,他们不是数据本身的组织;而是一种机制,或地图,帮助你访问数据。数据本身就是我们需要联系的实际人。电话公司没有把城镇的住宅安排成一个有意义的序列,把房子从一个地方移到另一个地方,这样所有同一个垒球队的女孩就住在隔壁,房子也不是由居民的姓组织起来的。相反,它给你一本书,每个住宅包含一个条目。这些条目按白页搜索键、姓氏、名字、中间初始地址和街道地址排序。每个条目包含搜索键和允许您访问该住宅的一段数据;电话号码。
像一个进入白色的页面,在SQL Server的非聚集索引的每个条目包含两部分:
搜索关键字,如姓氏——名字——中间初始值。在SQL Server术语中,这是索引键。
该书签与电话号码的用途相同,允许SQLServer直接访问对应于该索引项的表中的行。
此外,SQL Server的非聚集索引条目有一些内部使用的标题信息,可能包含一些可选信息。这些都将被以后的水平;无论是重要的在这个时候对非聚集索引的理解。
与白页一样,SQLServer索引保持在搜索键序列中,以便任何特定条目都可以以小的“跳转”集合访问。给定搜索键,SQLServer可以快速获取该索引的索引项。与白页不同,SQLServer索引是动态的。也就是说,SQL Server每次添加一行、删除一个索引或修改一个搜索键列值时都会更新索引。
就像在不一样的城镇住宅的地理顺序在白色页的条目序列;非聚集索引中的项目的顺序不为表中的行序列相同。索引中的第一个条目可能是表中最后一行,索引中的第二个条目可能是表中第一行的条目。事实上,不同指标,其作品始终是一个有意义的序列;一个表的行完全可以编序。
创建索引时,SQL Server在底层表中的每一行中生成和维护索引中的一个条目(在覆盖过滤索引时,稍后将遇到这个一般规则的异常)。你可以在表中创建多个非聚集索引,但你不可能有一个指数包含来自多个表中的数据。
最大的区别是:SQL Server不能使用电话。它必须使用索引项的书签部分中的信息导航到表的相应行。当SQL Server需要数据行中的任何信息而不是相应的索引条目时,这一点是必需的,如Tracy Meyer的垒球帽大小。因此,为了更好地类比,一个白页条目包含一组GPS坐标而不是一个电话号码。然后使用GPS坐标导航到由白页条目表示的住所。
创建并受益于非聚集索引
我们通过两次查询我们的示例数据库来结束这个级别。确保你使用的是用于SQL Server 2005的版本中,可以使用的是SQL Server 2008。的adventureworks2008数据库具有不同的表结构和下面的查询将失败。我们将每次运行相同的查询;但是在我们在表上创建索引之前,第一个执行将发生,第二个执行将在我们创建索引之后。每次,SQLServer都会告诉我们在检索请求的信息时做了多少工作。我们将在联系人表中寻找“Helen Meyer”行(她的行位于表的中部)。最初,该表将不会有任何FirstName LastName列索引的列或。为了确保您可以多次运行该示例,请确保通过运行以下代码来确保我们将在第三批中构建的索引不存在:
IF EXISTS (SELECT * FROM sys.indexes
WHERE OBJECT_ID = OBJECT_ID('Person.Contact')
AND name = 'FullName')
DROP INDEX Person.Contact.FullName;
清单1.1——确保索引不存在
我们的任务将需要四个SQL命令批。
第一批命令:
SET STATISTICS io ON
SET STATISTICS time ON
GO
清单1.2打开统计数据
上面的批通知SQL Server,我们希望我们的查询作为输出的一部分返回性能信息。
第二批命令:
SELECT *
FROM Person.Contact
WHERE FirstName = 'Helen'
AND LastName = 'Meyer';
GO
清单1.3检索一些数据
第二批检索“Helen Meyer”行:
584 Helen Meyer helen2@adventure-works.com 0-519-555-0112
加上以下性能信息:
Table 'Contact'. Scan count 1, logical reads 569.
SQL Server Execution Times: CPU time = 3 ms.
这个输出告诉我们,我们的请求执行了569个逻辑IOS,并且需要大约3毫秒的处理器时间来完成。您的处理器时间值可能不同。
第三批命令:
CREATE NONCLUSTERED INDEX FullName
ON Person.Contact
( LastName, FirstName );
GO
清单1.4——创建非聚集索引
这批在Contact表中创建的第一个和最后一个名称列的非聚集综合指数。复合索引是一个多列决定索引行顺序的索引。
第四批命令:
SELECT *
FROM Person.Contact
WHERE FirstName = 'Helen'
AND LastName = 'Meyer';
GO
清单1.3(再次)
最后一批是对原始SELECT语句的重新执行。我们得到与以前相同的行;但是这次性能统计是不同的。
Table 'Contact'. Scan count 1, logical reads 4.
SQL Server Execution Times: CPU time = 0 ms.
这告诉我们,我们的要求输出只需要4个逻辑处理器时间和iOS;需要量小得检索“Helen Meyer”行。
结论
创建良好的索引可以大大提高数据库性能。在下一个层次,我们将开始查看索引的物理结构。我们将探讨为什么这个非聚集索引是查询如此有益,任何原因可能并非总是如此。未来将覆盖其他类型的指标,指标的附加利益,相关的成本指标,监控和维护你的指标和最佳实践;以提供你需要为你自己在你自己的数据库表创建最好的索引方案的知识目标
下载的代码
- Level 1 - IntroToIndexes_Durant_Code.sql
- Level 1 - MillionRowContactTable.sql
资源:
Level 1 - IntroToIndexes_Durant_Code.sql | Level 1 - MillionRowContactTable.sql
本文是SQL Server索引楼梯的一部分。