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


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...

面试题 相关文章推荐
PHP如何设置和取得Cookie值
Jun 30 面试题
C有"按引用传递"吗
Sep 06 面试题
寻找迷宫的一条出路,o通路;X:障碍
Jul 10 面试题
输入一行文字,找出其中大写字母、小写字母、空格、数字、及其他字符各有多少
Apr 15 面试题
SQL Server笔试题
Jan 10 面试题
一道写SQL的面试题和答案
Nov 19 面试题
OLEDBConnection和SQLConnection有什么区别
May 31 面试题
什么是动态端口(Dynamic Ports)?动态端口的范围是多少?
Dec 12 面试题
逻辑链路控制协议
Oct 01 面试题
外包公司软件测试工程师
Nov 01 面试题
介绍一下Python下range()函数的用法
Nov 07 面试题
Java文件和目录(IO)操作
Aug 26 面试题
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
支持php4、php5的mysql数据库操作类
2008/01/10 PHP
Base64在线编码解码实现代码 演示与下载
2011/01/08 PHP
phpmyadmin3 安装配置图解教程
2012/03/29 PHP
AJAX的跨域访问-两种有效的解决方法介绍
2013/06/22 PHP
php解决约瑟夫环示例
2014/04/09 PHP
使用 laravel sms 构建短信验证码发送校验功能
2017/11/06 PHP
php swoft框架实例用法
2020/12/22 PHP
文本框根据输入内容自适应高度的代码
2011/10/24 Javascript
判断输入是否为空,获得输入类型的JS代码
2013/10/30 Javascript
javascript自动给文本url地址增加链接的方法分享
2014/01/20 Javascript
js实现按一下删除键删除整个单词附demo
2014/09/05 Javascript
js中取得变量绝对值的方法
2015/01/03 Javascript
JavaScript中实现继承的三种方式和实例
2015/01/29 Javascript
jQuery实现仿微软首页感应鼠标变化滑动窗口效果
2015/10/08 Javascript
jQuery中使用animate自定义动画的方法
2016/05/29 Javascript
微信小程序实现滑动删除效果
2017/05/19 Javascript
详解JavaScript中的数组合并方法和对象合并方法
2018/05/11 Javascript
浅谈bootstrap layer.open中end的使用方法
2019/09/12 Javascript
[44:04]OG vs Mineski 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
python中正则的使用指南
2016/12/04 Python
python中virtualenvwrapper安装与使用
2018/05/20 Python
python set内置函数的具体使用
2019/07/02 Python
python使用for...else跳出双层嵌套循环的方法实例
2020/05/17 Python
flask开启多线程的具体方法
2020/08/02 Python
python 调用API接口 获取和解析 Json数据
2020/09/28 Python
Python+OpenCV图像处理—— 色彩空间转换
2020/10/22 Python
Html5实现iPhone开机界面示例代码
2013/06/30 HTML / CSS
Html5移动端div固定到底部实现底部导航条的几种方式
2021/03/09 HTML / CSS
英国灯具和灯泡网上商店:Lights.co.uk
2018/02/02 全球购物
物业管理员岗位职责范文
2013/11/25 职场文书
毕业生护理专业个人求职信范文
2014/01/04 职场文书
致跳远、跳高运动员广播稿
2014/01/09 职场文书
文明礼仪标语
2014/06/13 职场文书
2014年会计工作总结
2014/11/27 职场文书
pytorch 如何使用batch训练lstm网络
2021/05/28 Python
win10频率超出范围怎么办?win10老显示超出工作频率范围的解决方法
2022/07/07 数码科技