【译】索引进阶(一):SQL SERVER索引介绍
【译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正】
原文链接:http://www.sqlservercentral.com/articles/Stairway+Series/72284/
对于数据库设计来说,索引是至关重要的,它告诉了那些大量使用数据库的开发者其所使用的数据库的设计意图。然而不幸的是,在实际开发过程中,索引常常是作为一个性能问题发生时候的解决方案被添加上的。这一些列关于索引的介绍可以让你与专业的数据库设计人员保持思想及设计上的一致。
第一节介绍SQL SERVER的索引,它是使SQL SERVER在最小的时间内查询或者修改所要请求的数据的一种数据库对象,它目的在于使用最小的系统资源达到最大的性能优化。除此之外,好的索引设计可以保证数据库达到最大的并发数,这样一个用户的 查询就几乎不会影响另一个用户的查询请求。最后,索引提供了保证数据一致性的有效方式。这个章节只是对于索引的简单介绍,包含了基本的概念和用法,对于其具体的实现细节后续章节会予以描述。
对于数据库开发者来说,对于索引的总体理解显得特别重要,其原因之一在于:当一个对于SQL SERVER的请求从客户端到达时,SQL SERVER仅仅有两种可能的方式来访问到所所请求的数据:
# 它可以扫描数据库表的每一行数据,从第一行到最后一行,检查每一行来判断其是否满足所请求的查询条件。
# 或者,如果一个有用的索引存在,它会用此索引来直接定位到所请求的数据。
对于SQL SERVER来说,第一种选择总是可用的,而只有当你指导数据库创建了合适的索引之后,第二个选择才是可用的,但是他却可以导致突出的性能优化,如我们之后在本章所演示的那样。
因为索引是由开销的(它们占用一定的存储空间并必须与数据库表数据保持一致),他们不是SQL SERVER所必须的,很有可能一个数据库没有任何索引存在,也有可能它在性能提升上表现得 一般并且带来数据一致性的问题,但是SQL SERVER仍然允许它的存在。然而,索引带来的这些问题都不是我们想要的,我们都希望数据库性能优异,数据一致,同时索引开销尽可能的小,这一章节我们开始朝着这个目标前前进。
示例数据库
整个系列文章我们会用例子来演示关键概念,这些例子基于微软的AdventureWorks 示例数据库,我们关注于其销售订单功能上,如下五张表较好的混合了事务及非事务数据:Customer, SalesPerson, Product, SalesOrderHeader, and SalesOrderDetail,为了保证我们的关注点,我们使用其部门列数据。
AdventureWorks 具有良好的数据库设计结构,因此销售人员信息分散在三个表中:SalesPerson, Employee and Contact。对于一些例子来说,我们将其看作是一张表,我们将用到的所有表以及它们之间的关系如下图所示:

什么是索引
我们以一个简短的故事来开始对于索引的研究:
你由于一些事务离开了你的房子,当你回来的时候,你发现一条来自于自己女儿足球教练的信息等你处理,信息说有三个女孩:Tracy,Rebecca,Amy 搞丢了她们的帽子。请你务必去趟体育用品商店为姑娘们买下帽子,她们的家长会在下一次比赛时候偿还你的。
你认识这些女孩和她们的家长,而且很乐意帮女孩们买帽子,但是却不知道女孩们的帽子的大小,你需要的信息在女孩们位于镇里的住宅中,没有问题,你立即打电话给她们的家长从而可以获取这些信息。第一个你需要到达的住宅是Helen Meyer,假设Meyer处于zholn中间位置,你翻到黄页中间,翻到合适的页,然后扫描那些名字,找到“Meyer, Helen” 行,然后便得到了电话号码,用这个电话号码,你到达了他的房子然后得到了你所要的信息:帽子的大小。
按如上步骤重复两次,你到达了另外两个住宅,得到了另两个大小。
你正是使用了索引,并且你使用索引的方式和SQL SERVER使用索引的方式很像,在电话号码黄页与数据库索引之间具有很大的相似性及些许差别。
实际上,刚才你所使用的索引代表了SQL SERVER支持的两种数据库索引之一:非聚集索引。另一种是聚集索引,本章节重点介绍非聚集索引,后续章节会介绍聚集索引,并对两种类型的索引做深入分析。
非聚集索引
电话号码黄页类比于数据库的非聚集索引,其原因在于它们不是实际数据的组织形式,而是一种映射,帮助你访问到实际数据,数据本身是我们需要联系的人,电话公司不会安排城镇的住宅为一个有意义的序列,他们不会把房间从一个地点移动到另一个地点从而保证在一个足球队的女孩都住在一起,并且,房子也不会按照居民的姓氏排列,反而,电话号码本只是给你一个书签,包含了到达各个住宅的入口点,这些入口点按电话号码本的搜索键排列,就是姓氏,各个入口点包含了搜索键和使你能够到达住宅的数据:电话号码。
如同电话号码的入口点,SQL SERVER非聚集索引的入口点也包含两部分。
# 检索键:例如姓氏,在SQL SERVER术语来说:这就是 索引键;
# 书签:类比于企业黄页中的电话号码,允许SQL SERVER直接导航至于此检索键交互的表数据行中。
除此之外,非聚集索引入口点还包含一些仅供内部使用的头信息,以及一些可选的信息,后续章节会对这些内容进行介绍,此刻对于理解非聚集索引来说,这些知识无关紧要。
像电话号码本一般,SQL SERVER索引按序列化的检索键组织起来,这样任何一个入口点可以通过数个跳转来达到。给定一个检索键,SQL SERVER可以快速的到达这个键对应的索引入口点,不同于电话本的是,SQL SERVER索引是动态的,这意味着SQL SERVER会在每一次数据的数据添加,移除,或者检索键发生更改时候更新相关索引。
电话号码本的排列顺序与住宅在地里位置上的排列顺序是不一样的,非聚集索引入口点的排列顺序与数据表中行的排列顺序也是不一样的。第一个入口点可能代表了表中的最后一行,第二个入口点则可能代表了数据库表中的第一行。正如事实上的,虽然数据库索引键是有意义的排列,一个表的行则可能是毫无顺序的。
当我们创建了一个索引,SQL SERVER索引中为表中的每一行数据都产生并且维护了一个入口点,你可以在一个表上创建多个非聚集索引,但是却无法创建索引包含两个表的数据,一个索引的局限于一个表结构。
其最大的不同在于,SQL SERVER不能使用电话号码,它必须使用索引入口点中书签部分的信息来导航到相应的行。当SQL SERVER需要一些在数据行中的信息但却不在入口点中的信息时,这个是非常必要的。
类似的,电话号码本可以包含一组GPS坐标信息而不是电话号码,你便可以用此GPS坐标导航至相应的住宅。
创建非聚集索引
我们通过两次查询示例数据库来结束本章节的介绍,确保你使用的AdventureWorks示例数据库是用于SQL SERVER 2005 版本的,当然它可以被后续版本使用,AdventureWorks2008版本数据库在表结构上会有些不同,导致如下查询失败。每次我们都会运行相同的查询,第一次执行时候,我们并没有创建索引,索引创建之后,我们执行第二次查询,每一次,SQL SERVER会告诉我们为了返回所请求的数据,多少工作被完成。我们将在Contact 表中查询“Helen Meyer”,最初在FirstName,LastName 表不存在任何索引。
为了确保我们可以多此运行我们的例子,保证我们将创建的索引不存在,我们可以运行如下SQL:
IF EXISTS (SELECT * FROM sys.indexes
WHERE OBJECT_ID = OBJECT_ID('Person.Contact')
AND name = 'FullName')
DROP INDEX Person.Contact.FullName; 我们的任务需要执行4个SQL批量处理语句。 第一个SQL:
SET STATISTICS io ON
SET STATISTICS time ON
GO
上述命令通知SQL SERVER我们期望各个查询在输出部分返回性能信息。 第二个SQL:
SELECT *
FROM Person.Contact
WHERE FirstName = 'Helen'
AND LastName = 'Meyer';
GO
上述语句返回信息:584 Helen Meyer helen2@adventure-works.com 0-519-555-0112
同时性能信息也被返回:如图
可以看出来我们的请求数据需要569次逻辑IO,需要毫秒去处理,你本地运行的时间可能不同。
接着我们创建索引:
CREATE NONCLUSTERED INDEX FullName
ON Person.Contact
( LastName, FirstName );
GO
上述语句创建了非聚集组合索引,所谓组合索引便是索引列超过一列的索引。
我们再次执行上述查询:
SELECT *
FROM Person.Contact
WHERE FirstName = 'Helen'
AND LastName = 'Meyer';
GO 这次性能数据不同:

结论
谨慎选择的索引能极大的改进数据库的性能,下一节我们将研究索引的物理结构,我们将检查为何非聚集索引对于我们的查询如此有益,以及为何并不总是如此有益,后续章节会包含其他类型的索引,以及索引的额外好处,索引的开销,监控并维护你的索引,以及最佳实践,所有着一切的目标在于提供给我们必要的知识,来为自己的数据库表创建最适宜的索引架构。
【译】索引进阶(一):SQL SERVER索引介绍的更多相关文章
- c#Winform程序调用app.config文件配置数据库连接字符串 SQL Server文章目录 浅谈SQL Server中统计对于查询的影响 有关索引的DMV SQL Server中的执行引擎入门 【译】表变量和临时表的比较 对于表列数据类型选择的一点思考 SQL Server复制入门(一)----复制简介 操作系统中的进程与线程
c#Winform程序调用app.config文件配置数据库连接字符串 你新建winform项目的时候,会有一个app.config的配置文件,写在里面的<connectionStrings n ...
- SQL Server索引碎片整理实际操作记录
SQL Server 版本是 2008 R2. 查询数据库索引碎片情况的 SQL 语句(来源): SELECT OBJECT_NAME(ind.OBJECT_ID) AS TableName, ind ...
- SQL Server索引总结二
从CREATE开始 通过显式的CREATE INDEX命令 在创建约束时作为隐含的对象 随约束创建的隐含索引 当向表中添加如下两种约束之一时,就会创建隐含索引. 主键约束(聚集索引) 唯一约束(唯一索 ...
- 【译】SQL Server索引进阶第八篇:唯一索引
原文:[译]SQL Server索引进阶第八篇:唯一索引 索引设计是数据库设计中比较重要的一个环节,对数据库的性能其中至关重要的作用,但是索引的设计却又不是那么容易的事情,性能也不是那么轻易就 ...
- SQL Server索引进阶:第十级,索引内部结构
原文地址: Stairway to SQL Server Indexes: Level 10,Index Internal Structure 本文是SQL Server索引进阶系列(Stairway ...
- SQL Server索引进阶:第八级,唯一索引
原文地址: Stairway to SQL Server Indexes: Level 8,Unique Indexes 本文是SQL Server索引进阶系列(Stairway to SQL Ser ...
- SQL Server索引进阶:第六级,标签
原文地址: Stairway to SQL Server Indexes: Level 6,Bookmarks 本文是SQL Server索引进阶系列(Stairway to SQL Server I ...
- SQL Server索引进阶:第五级,包含列
原文地址: Stairway to SQL Server Indexes: Level 5, Included Columns 本文是SQL Server索引进阶系列(Stairway to SQL ...
- SQL Server索引进阶:第四级,页和区
原文地址: Stairway to SQL Server Indexes: Level 4, Pages and Extents 本文是SQL Server索引进阶系列(Stairway to SQL ...
随机推荐
- 可视化工具Grafana:简介及安装
随着业务的越发复杂,对软件系统的要求越来越高,这意味着我们需要随时掌控系统的运行情况.因此,对系统的实时监控以及可视化展示,就成了基础架构的必须能力. 这篇博客,介绍下开源的可视化套件grafana的 ...
- Jquery mobile动态生成ListView调用刷新方法报错
错误:cannot call methods on listview prior to initialization... 示例: <div data-role="page" ...
- Git入门—创建项目
Git入门—创建项目 注:win10系统下 打开Git Bash,进入存放仓库的目录 创建 初始化git init,该命令执行完后会在当前目录生成一个 .git 目录. 所有 Git 需要的数据和资源 ...
- [第二届构建之法论坛] 预培训文档(Java版)
本博客是第二届构建之法论坛暨软件工程培训活动预培训文档中[适用于结对编程部分的Java版本],需要实验者有一部分Java基础. 目录 Part0.背景 Part1.配置环境 配置JDK Linux 平 ...
- sql 日常使用记录
sql 某个字段在哪些表中存在: select sysobjects.name from syscolumns inner join sysobjects on syscolumns.id = sys ...
- spring boot 操作MySQL pom添加的配置
1 在项目中的pom.xml配置文件添加依赖 <!--MySQL依赖 --> <dependency> <groupId>mysql</groupId> ...
- Python抓取天气信息并存储原来这么简单
我们计划抓取的数据:杭州的天气信息 实现数据抓取的逻辑:使用python 请求 URL,会返回对应的 HTML 信息,我们解析 html,获得自己需要的数据.(很简单的逻辑) 第一步:创建 Pytho ...
- 通过CONN_MAX_AGE优化Django的数据库连接
上周对我们用Django+Django-rest-framework提供的一套接口进行了压力测试.压测的过程中,收到DBA通知——数据库连接数过多,希望我们优化下程序.具体症状就是,如果设置mysql ...
- idea中war和war exploded的区别及修改jsp必须重新启动tomcat才能生效的问题
刚开始使用idea,发现工程每次修改JS或者是JSP页面后,并没有生效,每次修改都需要重启一次Tomcat这样的确不方便.我想Idea肯定有设置的方法,不可能有这么不方便的功能存在. 需要在Tomca ...
- QT出现应用程序无法正常启动0xc000007b的错误
最近做了一个成绩管理系统,打包好后,运行他的exe可执行文件时,出现了如下图的错误提示: 在网上查阅了很多资料,其中有篇文章给了我很大的启示和帮助,文章地址http://www.cnblogs.com ...
