SQL Server聚集索引的选择

先声明文章非原创,摘自博客园:http://www.cnblogs.com/CareySon/archive/2012/03/06/2381582.html

简介

   在SQL Server中,数据是按页进行存放的。而为表加上聚集索引后,SQL Server对于数据的查找就是按照聚集索引的列作为关键字进行了。因此对于聚集索引的选择对性能的影响就变的十分重要了。本文旨在从性能角度来谈聚集索引的选择,但这仅仅是从性能方面考虑。对于有特殊业务要求的表,则需要按实际情况进行选择。

一、聚集索引所在列或列的组合最好是唯一的

   这个原因需要从数据的存放原理来谈。在SQL Server中,数据的存放方式并不是以行(Row)为单位,而是以页为单位。因此,在查找数据时,SQL Server查找的最小单位实际上是页。也就是说即使你只查找一行很小的数据,SQL Server也会将整个页查找出来,放在缓冲池中。

  每一个页的大小是8K。每个页都会有一个对于SQL Server来说的物理地址。这个地址的写法就是文件号:页号(理解文件号需要你对文件和文件组有所理解)。比如第一个文件的第50页。则页号为:1:50。当表没有聚集索引时,表中的数据页是以堆(Heap)进行存放的,在页的基础上,SQL Server通过一个额外的行号来确定每一行,这也是传说中的RID。RID是文件号:页号:行号来进行表示的,假设这一行在起前面所说的页中的第5行,则RID表示为1:50:5,如图1所示:

  从RID的概念来看,RID不仅仅是SQL Server唯一确定每一行的数据,也是存放行的存放位置。当页通过堆(Heap)进行组织时,页很少进行移动。

  而当表上建立索引时,表中的页按照B树进行组织。此时,SQL Server寻找行不再是按RID进行查找,转而使用了关键字,也就是聚集索引的列作为关键字进行查找。假设图1的表中,我们设置DepartmentID列作为聚集索引列。则B树的非叶子节点的行中只包含了DepartmentID和指向下一层结点的书签(BookMark)。

  而当我们创建的聚集索引的值不唯一时,SQL Server则无法仅仅通过聚集索引列(也就是关键字)唯一确定一行。此时,为了实现对每一行的唯一区分,则需要SQL Server为相同值的聚集索引生成一个额外的标示信息进行区分,这也是所谓的uniquifiers。而使用了uniquifier后,对性能产生的影响分为如下部分:

1、SQL Server必须在插入或者更新时对现在的数据进行判读是否和现有的键重复,如果重复,则需要生成uniqifier,这个是一笔额外开销。

2、因为需要对相同值的键添加额外的uniquifier来区分,因此键的大小被额外的增加了。因此无论是叶子节点和非叶子节点,都需要更多的页进行存储。从而还影响到非聚集索引,使得非聚集索引的书签列变大,从而使得非聚集索引也需要进行更多的页进行存储。

下面我们进行测试,创建一个测试表,创建聚集索引。插入10W条测试,其中每2条一重复,如图2所示。

--创建测试表
create table [dbo].[TestP]
([id] int,[Name] varchar(100)
)
go--在id上创建聚集索引
create clustered index testp_cindex on TestP(id)
go
--插入10W条数据测试,每2条一重复
begin tran
declare  @index int
set @index=0
while(@index<100000)
begin insert into dbo.TestP(id,Name)values(@index,'测试数据')insert into dbo.TestP(id,Name)values(@index,'测试数据')
set @index=@index+1
end
commitexec sp_spaceused 'TestP'

我们插入了测试数据
此时,我们来查看这个表所占的页数,如图3所示。

插入重复键后10W数据占了359页

我们再次插入10W不重复的数据,如图所示

    此时,所占页数缩减为335页,如图5所示。

         因此,推荐聚集索引所在列使用唯一键。

二、最好使用窄列或窄列组合作为聚集索引列

    这个道理和上面减少页的原理一样,窄列使得键的大小变小。使得聚集索引的非叶子节点减少,而非聚集索引的书签变小,从而叶子节点页变得更少。最终提高了性能。

 

三、使用值很少变动的列或列的组合作为聚集索引列

    在前面我们知道。当为表创建聚集索引后。SQL Server按照键查找行。因为在B数中,数据是有序的,所以当聚集索引键发生改变时,不仅仅需要改变值本身,还需要改变这个键所在行的位置(RID),因此有可能使得行从一页移动到另一页。从而达到有序。因此会带来如下问题:

  •     行从一页移动到另一页,这个操作是需要开销的,不仅如此,这个操作还可能影响到其他行,使得其他行也需要移动位置,有可能产生分页
  •     行在页之间的移动会产生索引碎片
  •     键的改变会影响到非聚集索引,使得非聚集索引的书签也需要改变,这又是一笔额外的开销

     这也就是为什么很多表创建一列与数据本身无关的列作为主键比如AdventureWorks数据库中的Person.Address表,使用AddressID这个和数据本身无关的列作为聚集索引列,如图6所示。而使用AddressLine1作为主键的话,员工地址的变动则可能造成上面列表的问题。

    6

    图6.创建和数据本身无关的一列作为聚集索引列

 

四、最好使用自增列作为聚集索引列

    这个建议也同样推荐创建一个和数据本身无关的自增列作为聚集索引列。我们知道,如果新添加进来的数据如果聚集索引列需要插入当前有序的B树中,则需要移动其它的行来给新插入的行腾出位置。因此可能会造成分页和索引碎片。同样的,还会造成修改非聚集索引的额外负担。而使用自增列,新行的插入则会大大的减少分页和碎片。

   最近我碰到过一个情况。一个表每隔几个月性能就奇慢无比,初步查看是由于有大量的索引碎片。可是每隔几个月重建一次索引让我无比厌烦。最终我发现,问题是由于当时设计数据库的人员将聚集索引建在了GUID上,而GUID是随机生成的,则可能插入到表的任何位置,从而大大增加了碎片的数量。因此造成上面这种情况。

 

总结

    本文简单介绍了SQL Server存储的原理和应该规避的几种聚集索引建立情况,但这仅仅是从性能的角度来谈聚集索引的选择。对于聚集索引的选择,还是需要全面的考虑进行决定。

 

 

 

转载于:https://www.cnblogs.com/zhijianliutang/archive/2012/05/16/2505552.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/260825.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++突破网关屏蔽_为什么加了屏蔽罩,测试效果反而不好?

来自专治PCB疑难杂症微信群群友(群友突破1200人啦&#xff0c;文末添加杨老师微信号&#xff0c;可添加入群)的问题讨论&#xff1a;设计时我加了屏蔽罩&#xff0c;结果在测试的时候不加屏蔽罩的效果要比加了屏蔽罩的效果好&#xff0c;这是为何&#xff1f;跟PCB设计的屏蔽罩…

第3章 Python 数字图像处理(DIP) - 灰度变换与空间滤波6 - 分段线性变换 - 比特平面分层

目录比特平面分层比特平面分层 在一幅256级灰度图像中&#xff0c;图像的值是由8比特&#xff08;1字节&#xff09;组成的 def convert_bin(data, n):"""convert decimal to binary, return n th bit, 0 if bit value 0 else 1""" #---------…

iOS GCD

from&#xff1a;http://www.cnblogs.com/dsxniubility/p/4296937.html 一般&#xff1a; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{// 耗时操作dispatch_async(dispatch_get_main_queue(), ^{// 更新UI});}); 本文是对以往学习的多线…

c++和java哪个难_2020 年 11 月编程语言排行榜,Python 超越 Java ?

来源&#xff1a;tiobe.com/tiobe-index/November-2020TIOBE 2020 年 11 月份的编程语言排行榜已经公布&#xff0c;官方的标题是&#xff1a;Python 势如破竹&#xff0c;超越 Java。题外话: 目前小哈正在个人博客(新搭建的网站&#xff0c;域名就是犬小哈的拼音) www.quanxia…

C# 温故而知新:Stream篇(七)

C# 温故而知新&#xff1a;Stream篇&#xff08;七&#xff09; NetworkStream 目录&#xff1a; NetworkStream的作用简单介绍下TCP/IP 协议和相关层次简单说明下 TCP和UDP的区别简单介绍下套接字&#xff08;Socket&#xff09;的概念简单介绍下TcpClient,TcpListener,IPEndP…

第3章 Python 数字图像处理(DIP) - 灰度变换与空间滤波7 - 直方图处理 - 直方图、归一化直方图

目录直方图处理直方图处理 令rk,k0,1,2,…,L−1r_k, k0, 1, 2, \dots, L-1rk​,k0,1,2,…,L−1表于一幅LLL级灰度数字图像f(x,y)f(x,y)f(x,y)的灰度。fff的非归一化直方图定义为&#xff1a; h(rk)nk,k0,1,2,…,L−1(3.6)h(r_{k}) n_{k}, \quad k 0, 1, 2, \dots, L-1 \tag{…

Xamarin Android提示找不到资源属性定义

为什么80%的码农都做不了架构师&#xff1f;>>> Xamarin Android提示找不到资源属性定义 错误信息&#xff1a;”Resource.Attribute”未包含”actonBarSize”的定义 Xamarin Android经常会出现找不到资源属性的错误。遇到这种问题&#xff0c;建议先清理解决方法和…

MAC OS X 1.1 El Capitan安装方法与步骤

2019独角兽企业重金招聘Python工程师标准>>> 苹果公司发布了最新的Mac系统El Capitan,我也跟风安装了, 昨天试了一天终于算是安装成功了. ###电脑配置: CPU: E3-1230 v2 主板: 技嘉B75M D3V 显卡: 微星6850 声卡: Realtek ALC887 键盘: Noppoo 84键机械键盘 ###下载…

vp与vs联合开发-网口通信(socket)

Socket通信是一种在网络中进行进程间通信的机制。它使用了一种称为套接字&#xff08;Socket&#xff09;的编程接口&#xff0c;通过该接口可以创建、连接、发送和接收数据等操作。 Socket通信中&#xff0c;有两个主要的角色&#xff1a;服务器和客户端。服务器负责监听指定…

第3章 Python 数字图像处理(DIP) - 灰度变换与空间滤波8 - 直方图处理 - 直方图均衡化(全局直方图均衡化)

直方图均衡化 灰度映射函数&#xff1a; sT(r),0≤r≤L−1(3.8)s T(r), \quad 0\leq r \leq L -1 \tag{3.8}sT(r),0≤r≤L−1(3.8) 假设&#xff1a; (1) T(r)T(r)T(r)在区间0≤r≤L−10 \leq{r} \leq{L-1}0≤r≤L−1 上是一个单调递增函数。 (2) 对于0≤r≤L−10 \leq{r} …

python 元组和列表区别_Python干货整理:一分钟了解元组与列表使用与区别

元组是 Python 对象的集合&#xff0c;跟列表十分相似。下面进行简单的对比。列表与元组1、python中的列表list是变量&#xff0c;而元组tuple是常量。列表&#xff1a;是使用方括号[]&#xff0c;元组&#xff1a;则是使用圆括号()2、两者都可以使用索引读取值列表1.列表中的a…

Maven for Eclipse 第二章 ——安装 m2eclipse插件

m2eclipse 是一个提供了 Maven 与 Eclipse 整合的插件。它的意图是桥接上 Maven 和 Eclipse 之间的缺口。通过 Maven 原型提供的简单直白的接口创建项目&#xff0c;它使 Maven 在 IDE 中非常容易使用。下面是m2eclipse 提供的一些特性。 创建和导入 Maven 项目在 Eclipse 运行…

第3章 Python 数字图像处理(DIP) - 灰度变换与空间滤波9 - 直方图处理 - 直方图匹配(规定化)灰度图像,彩色图像都适用

直方图匹配&#xff08;规定化&#xff09; 连续灰度 sT(r)(L−1)∫0rpr(w)dw(3.17)s T(r) (L-1) \int_{0}^{r} p_r(w) \text{d} w \tag{3.17} sT(r)(L−1)∫0r​pr​(w)dw(3.17) 定义关于变量zzz的一个函数GGG&#xff0c;它具有如下性质&#xff1a; G(z)(L−1)∫0zpz(v)d…

C#委托之就是跟委托过不去…

在上一篇博文当中,我们例举了一个机房自动化系统的逻辑控制程序,其中用到了Lambda表达式,因此方便了我们程序功能的实现.然而,我们不能仅仅为实现功能,完成任务而奋斗,应该知其然,知其所以然,也就是说,知道了Lambda表达式能够带来这样的方便,也应该知道为什么能够带来这样的方便…

closewait一直不释放_机床为什么要释放应力?怎么释放应力才好?

在机床行业内一直有种说法&#xff0c;就是机床需要释放应力&#xff0c;而且越是高精密的机床就越要注意应力的释放&#xff0c;最近就有机床粉向小编询问应力是什么&#xff1f;为什么要释放应力&#xff1f;如果释放要释放多久&#xff1f;怎么释放应力才好等一系列关于机床…

HDU 1025 Constructing Roads In JGShining's Kingdom(DP+二分)

点我看题目 题意 &#xff1a;两条平行线上分别有两种城市的生存&#xff0c;一条线上是贫穷城市&#xff0c;他们每一座城市都刚好只缺乏一种物资&#xff0c;而另一条线上是富有城市&#xff0c;他们每一座城市刚好只富有一种物资&#xff0c;所以要从富有城市出口到贫穷城市…

表单元素选择器

无论是提交还是传递数据&#xff0c;表单元素在动态交互页面的作用是非常重要的。jQuery中专门加入了表单选择器&#xff0c;从而能够极其方便地获取到某个类型的表单元素 表单选择器的具体方法描述&#xff1a; 注意事项&#xff1a; 除了input筛选选择器&#xff0c;几乎每个…

怎样在excel表格中画斜线并打字_一日一技丨Excel斜线表头如何制作?标题、表头的4个技巧...

来源 | 迅捷PDF转换器 (ID:xjpdf6)作者丨小小迅「一日一技」是每天的知识分享专栏&#xff0c;一是分享一些PDF、Office、办公小技巧&#xff1b;二是抽取小可爱们在留言中的疑问并解决。希望对大家有所帮助&#xff01;表头的标题是Excel中的第一道大门&#xff0c;精致好看的…

Retina时代的前端视觉优化

随着New iPad的发布&#xff0c;平板也将逐渐进入Retina时代&#xff0c;在高分辨率设备里图片的显示效果通常不尽人意&#xff0c;为了达到最佳的显示效果就需要对图片进行优化&#xff0c;这里介绍一些优化方法&#xff1a; 一、用CSS替代图片 这一点在任何时候都适用&#x…

第3章 Python 数字图像处理(DIP) - 灰度变换与空间滤波10 - 直方图处理 - 局部直方图处理

这里写目录标题局部直方图处理局部直方图处理 因为像素是由基于整个图像的灰度的变换函数修改的。这种全局性方法适合于整体增强&#xff0c;但当目的是增强图像中几个小区域的细节时&#xff0c;通常就会失败。这是因为在这些小区域中&#xff0c;像素的数量对计算全局变换的…