什么是聚集索引和非聚集索引


Posted in 面试题 onJanuary 17, 2012
(1)非聚集索引
非聚集索引与课本中的索引类似。数据存储在一个地方,索引存储在另一个地方,索引带有指针指向数据的存储位置。索引中的项目按索引键值的顺序存储,而表中的信息按另一种顺序存储(这可以由聚集索引规定)。如果在表中未创建聚集索引,则无法保证这些行具有任何特定的顺序。

典型的桌面数据库使用的是非聚集索引。在这类索引中,索引键值是有序的,而每个索引节点所指向的数据行是无序的。一个SQL Server表最多可以拥有255个非聚集索引。

非聚集索引与聚集索引一样有 B-树结构,但是有两个重大差别:
1、数据行不按非聚集索引键的顺序排序和存储。
2、非聚集索引的叶层不包含数据页。
相反,叶节点包含索引行。每个索引行包含非聚集键值以及一个或多个行定位器,这些行定位器指向有该键值的数据行(如果索引不唯一,则可能是多行)。非聚集索引可以在有聚集索引的表、堆集或索引视图上定义。在 SQL Server中,非聚集索引中的行定位器有两种形式:
1、如果表是堆集(没有聚集索引),行定位器就是指向行的指针。该指针用文件标识符 (ID)、页码和页上的行数生成。整个指针称为行 ID。
2、如果表是堆集(没有聚集索引),行定位器就是指向行的指针。该指针用文件标识符 (ID)、页码和页上的行数生成。整个指针称为行 ID。
由于非聚集索引将聚集索引键作为其行指针存储,因此使聚集索引键尽可能小很重要。如果表还有非聚集索引,请不要选择大的列作为聚集索引的键。
在创建非聚集索引之前,应先了解您的数据是如何被访问的。可考虑将非聚集索引用于:
包含大量非重复值的列,如姓氏和名字的组合(如果聚集索引用于其它列)。如果只有很少的非重复值,如只有 1 和 0,则大多数查询将3、不使用索引,因为此时表扫描通常更有效。
1、不返回大型结果集的查询。
2、返回精确匹配的查询的搜索条件(WHERE 子句)中经常使用的列。
3、经常需要联接和分组的决策支持系统应用程序。应在联接和分组操作中使用的列上创建多个非聚集索引,在任何外键列上创建一个聚集索引。
4、在特定的查询中覆盖一个表中的所有列。这将完全消除对表或聚集索引的访问。

(2)聚集索引
聚集索引确定表中数据的物理顺序。聚集索引类似于电话簿,后者按姓氏排列数据。由于聚集索引规定数据在表中的物理存储顺序,因此一个表只能包含一个聚集索引。但该索引可以包含多个列(组合索引),就像电话簿按姓氏和名字进行组织一样。
聚集索引在系统数据库表sysindexes 内有一行,其 indid = 1。数据链内的页和其内的行按聚集索引键值排序。所有插入都在所插入行中的键值与排序顺序相匹配时执行。
SQL Server将索引组织为B-树。索引内的每一页包含一个页首,页首后面跟着索引行。每个索引行都包含一个键值以及一个指向较低级页或数据行的指针。索引的每个页称为索引节点。B-树的顶端节点称为根节点。索引的底层节点称为叶节点。每级索引中的页链接在双向链接列表中。在聚集索引内数据页组成叶节点。根和叶之间的任何索引级统称为中间级。
对于聚集索引,sysindexes.root 指向它的顶端。SQL Server 沿着聚集索引浏览以找到聚集索引键对应的行。为找到键的范围,SQL Server 浏览索引以找到这个范围的起始键值,然后用向前或向后指针扫描数据页。为找到数据页链的首页,SQL Server 从索引的根节点开始沿最左边的指针进行扫描.
聚集索引对于那些经常要搜索范围值的列特别有效。使用聚集索引找到包含第一个值的行后,便可以确保包含后续索引值的行在物理相邻。例如,如果应用程序执行的一个查询经常检索某一日期范围内的记录,则使用聚集索引可以迅速找到包含开始日期的行,然后检索表中所有相邻的行,直到到达结束日期。这样有助于提高此类查询的性能。同样,如果对从表中检索的数据进行排序时经常要用到某一列,则可以将该表在该列上聚集(物理排序),避免每次查询该列时都进行排序,从而节省成本。
对于聚集索引,人们往往有一些错误的认识。其中,最常见的错误有:
1、聚集索引会降低insert操作的速度,因为必须要向后移动一半的数据来为新插入的行腾出空间。这种认识是错误的,因为可以利用填充因子控制填充的百分比,从而在索引页上为新插入的数据保留空间。如果索引页填满了,SQL Server将会进行页拆分,在这种情况下只有第一个页才会受到影响。
2、在使用标识列的主键上创建聚集索引是一种好的设计方法,它可以使对表的操作达到最快速度。这种认识是错误的,它浪费了创建其它更有效的聚集索引的机会。并且,使用这种方法会把每个新插入的记录行都存储到表尾部的同一个的数据页中,这将导致数据库的热点和锁争用。笔者曾经见过采用这种方法设计的数据库,对于每一个新订单,客户服务人员都不得不等待数分钟来加以确认。
3、聚集索引是具有魔力的。如果哪个查询的速度不够快,那么就在该列上创建聚集索引,对于表的操作速度一定会得到提高。这种认识也是错误的,聚集索引只是比非聚集索引稍稍快了那么一点点。因为在每个表上只能创建一个聚集索引,所以它也是一种宝贵的性能资源,只有在那些经常作为条件查询一组记录行的列上才应该建立聚集索引。

在创建聚集索引之前,应先了解数据是如何被访问的。可考虑将聚集索引用于:
1、包含大量非重复值的列。
2、使用下列运算符返回一个范围值的查询:BETWEEN、>、>=、 3、被连续访问的列。
4、返回大型结果集的查询。
5、经常被使用联接或 GROUP BY 子句的查询访问的列;一般来说,这些是外键列。对 ORDER BY 或 GROUP BY 子句中指定的列进行索引,可以使 SQL Server 不必对数据进行排序,因为这些行已经排序。这样可以提高查询性能。
6、OLTP 类型的应用程序,这些程序要求进行非常快速的单行查找(一般通过主键)。应在主键上创建聚集索引。
注意,聚集索引不适用于:
1、频繁更改的列,这将导致整行移动(因为 SQL Server 必须按物理顺序保留行中的数据值)。这一点要特别注意,因为在大数据量事务处理系统中数据是易失的。
2、宽键,来自聚集索引的键值由所有非聚集索引作为查找键使用,因此存储在每个非聚集索引的叶条目内。

Tags in this post...

面试题 相关文章推荐
新浪网技术部笔试题
Aug 26 面试题
介绍一下Java的安全机制
Jun 28 面试题
求网格中的黑点分布
Nov 06 面试题
C++:memset ,memcpy和strcpy的根本区别
Apr 27 面试题
将"引用"作为函数返回值类型的格式、好处和需要遵守的规则
Feb 09 面试题
使用索引有什么好处
Jul 27 面试题
网络安全方面的面试题
Jan 07 面试题
Windows和Linux动态库应用异同
Jul 28 面试题
某/etc/fstab文件中的某行如下: /dev/had5 /mnt/dosdata msdos defaults,usrquota 1 2 请解释其含义
Apr 11 面试题
中间件分为哪几类
Mar 14 面试题
Ajax和javascript的区别
Jul 20 面试题
ajax是什么及其工作原理
Feb 08 面试题
Oracle中delete,truncate和drop的区别
May 05 #面试题
什么是唯一索引
Jul 05 #面试题
主键(Primary Key)约束和唯一性(UNIQUE)约束的区别
May 29 #面试题
介绍一下SQL中union,intersect和minus
Apr 05 #面试题
叙述DBMS对数据控制功能有哪些
Jun 12 #面试题
SQL里面IN比较快还是EXISTS比较快
Jul 19 #面试题
什么是触发器(trigger)? 触发器有什么作用?
Sep 18 #面试题
You might like
实现树状结构的两种方法
2006/10/09 PHP
php微信开发之百度天气预报
2016/11/18 PHP
PHP simplexml_load_string()函数实例讲解
2019/02/03 PHP
JavaScript 对Cookie 操作的封装小结
2009/12/31 Javascript
javascript中字符串拼接需注意的问题
2010/07/13 Javascript
jquery中实现简单的tabs插件功能的代码
2011/03/02 Javascript
js DOM 元素ID就是全局变量
2012/09/20 Javascript
form表单中去掉默认的enter键提交并绑定js方法实现代码
2013/04/01 Javascript
『JavaScript』限制Input只能输入数字实现思路及代码
2013/04/22 Javascript
jQuery动画特效实例教程
2014/08/29 Javascript
基于javascript的COOkie的操作实现只能点一次
2014/12/26 Javascript
js实现微博发布小功能
2017/01/12 Javascript
浅谈react.js 之 批量添加与删除功能
2017/04/17 Javascript
JS实现动态添加DOM节点和事件的方法示例
2017/04/28 Javascript
微信小程序页面开发注意事项整理
2017/05/18 Javascript
关于javascript获取内联样式与嵌入式样式的实例
2017/06/01 Javascript
Angularjs自定义指令实现分页插件(DEMO)
2017/09/16 Javascript
Angular实现较为复杂的表格过滤,删除功能示例
2017/12/23 Javascript
Vue全局分页组件的实现代码
2018/08/10 Javascript
vue基于element-ui的三级CheckBox复选框功能的实现代码
2018/10/15 Javascript
vue配置接口域名方法总结
2019/05/12 Javascript
vue项目中使用rem,在入口文件添加内容操作
2020/11/11 Javascript
在python中只选取列表中某一纵列的方法
2018/11/28 Python
python 发送和接收ActiveMQ消息的实例
2019/01/30 Python
简单了解为什么python函数后有多个括号
2019/12/19 Python
Python预测2020高考分数和录取情况
2020/07/08 Python
Python同时迭代多个序列的方法
2020/07/28 Python
python实现发送QQ邮件(可加附件)
2020/12/23 Python
Alexandre Birman美国官网:亚历山大·伯曼
2019/10/30 全球购物
手术室护士长竞聘书
2014/03/31 职场文书
关爱留守儿童标语
2014/06/18 职场文书
2014年党员个人剖析材料
2014/10/08 职场文书
2014年客服工作总结与计划
2014/12/09 职场文书
微信搭讪开场白
2015/05/28 职场文书
详解MySQL的半同步
2021/04/22 MySQL
浅谈Go语言多态的实现与interface使用
2021/06/16 Golang