今天我们来探讨下聚集索引的设计要求。在选择聚集索引键时,有好几点需要考虑的。选择聚集索引键没有硬性规定。多实践,多从网上找问题的答案都会帮你找到正确的索引键。

唯一性(Uniqueness)

SQL Server允许你在非唯一列创建聚集索引,但是唯一性是任何索引最理想的属性,尤其对于聚集索引。即使SQL Server允许在非唯一列创建聚集索引,在内部,SQL Server会为所有聚集索引键的重复值增加4 bytes的值,这个4 bytes 变长列就是所谓的uniquifiers。在这个情况下,SQL Server在聚集索引上定义的非唯一列和内部生成的uniquifiers列的组合当作聚集键。这个值在每个聚集索引键都会保存。例如在聚集表上定义的非聚集索引的叶子层。

我们来看一个例子,创建SalesOrderDetail表的副本,并在productid 列(包含重复值)上定义一个聚集索引。

1 Use IndexDB
2 GO
3 SELECT * INTO dbo.SalesOrderDetailDupCI FROM AdventureWorks2008r2.Sales.SalesOrderDetail
4 GO
5 CREATE CLUSTERED INDEX ix_SalesOrderDetailDupCI ON dbo.SalesOrderDetailDupCI(ProductId)

我们通过DBCC INC命令看看它的分配页,并找出它的根页:

1 DBCC IND('IndexDB','SalesOrderDetailDupCI',1)
2
3 TRUNCATE TABLE dbo.sp_table_pages
4 INSERT INTO sp_table_pages EXEC('DBCC IND(IndexDB,SalesOrderDetailDupCI,1)')
5 GO
6
7 SELECT * FROM dbo.sp_table_pages ORDER BY IndexLevel DESC --根节点/索引页

可以看到5650页是根页(indexlevel列值为最大值2),我们用DBCC PAGE命令看下根页的内容。

1 DBCC TRACEON(3604)
2 DBCC PAGE(IndexDB,1,5650,3)

再用DBCC PAGE看看中间页5648的内容:

1 DBCC TRACEON(3604)
2 DBCC PAGE(IndexDB,1,5648,3)

可以看到,我们的中间级的索引页额外增加了UNIQUIFIER列,用来保证聚集索引键productid的唯一性。当聚集索引创建在非唯一列时,SQL Server会为重复出现的聚集键增加4 bytes的随机值,不重复的键不增加(第一条记录productid为NULL,是唯一不重复的,故UNIQUIFIER值也是NULL)。因此定义在非唯一列的聚集索引会额外生成UNIQUIFIER值,也就增加了聚集键的长度。productid列为int,长度为4 bytes,加上4 bytes的UNIQUIFIER,我们聚集键的长度也就变成了8 bytes。这个组合会复制到所有非聚集索引的叶子节点。当在非唯一列的聚集索引上创建非聚集索引时,这个问题会加剧,聚集索引值同样要保存到非叶子层的页里去。(下篇文章我们会讨论在非唯一列的聚集索引上创建非聚集索引的问题)。

如果一个表没有一个唯一键去定义聚集索引,可以考虑再加几个小列让它变成唯一。这样会避免UNIQUIFIER的出现,减少书签查找操作,因为非聚集索引的非页层有更多的列(这额外增加的列是为了保持聚集键的唯一性)。

静态的(Static)

另外一个聚集索引键的属性是静态的。当我们在非静态列定义聚集索引时,会让UPDATE语句更加耗费资源,为了保证记录是按聚集索引的逻辑顺序保存的,它需要把记录移到不同的页,同样非聚集索引的叶子层也要更新。

即使在小表的非静态列上定义聚集索引,且又定义一个非聚集索引在它上面。任何在在聚集索引键上个更改都要改动2个页。一个数据页,还有一个非聚集索引的叶子层页。

聚集索引键大小(Size of the clustered index key)

聚集索引键的大小指的是保存聚集索引键需要的字节数。当聚集索引键大小增加是,需要更多的IO操作来获取数据。这个发生是因为如果聚集索引更宽的话,索引页就只能保存更少的索引行。这就增加了中间层的页树,还有索引的深度(B树结构的层数)。例如,把聚集索引定义在整形列的话,一个包含数百万记录的表可能只需要3层的B树结构。如果把聚集索引定义在更宽的列(包含uniqueidentifier列需要16 bytes),那么索引的深度会增加到4(索引的层数)。任何聚集索引查找需要4个IO操作,原先只要3个IO。

这个问题也会传递到非聚集索引,因为聚集索引键也保存在所有非聚集索引的叶子层,作为指针指向聚集索引。如果非聚集索引定义在非唯一列,聚集键需要保存在非聚集索引的非页层页。同样也会带来更多的中间层页,并增加非聚集索引的深度。这也就增加非聚集索引查找/扫描的IO操作。因为聚集索引的深度增加到4,每个书签查找操作也会需要4个IO操作。

连续性(Sequential)

把聚集索引定义在自增长列(连续的)是个最佳做法。因为这个原因我们经常看到聚集索引定义在标识列(identity column)。聚集索引定义在非连续列会带来碎片。一个非连续的聚集索引列会强制SQL Server把记录插在中间(in between)用来保持数据的逻辑顺序。这会导致页分裂,也是造成外部和内部碎片的原因。

总结

我们已经讨论聚集索引设计的属性要求,还有它们背后的原因。在我们决定聚集索引键时,上述讨论的几点通常是最佳做法。除此之外,数据访问模式(data access pattern)也会影响我们聚集索引键的选择。

在我们没有完全理解数据访问模式前,我们需要用不同的方法测试下性能先。

参考文章:

http://www.sqlservercentral.com/blogs/practicalsqldba/2013/03/21/sql-server-part-6-design-consideration-of-clustered-index/

转载于:https://www.cnblogs.com/woodytu/p/4505699.html

索引深入浅出(6/10):选择正确并合适的聚集索引键相关推荐

  1. mysql如何建立索引workbench_MySQL数据库中如何正确的理解与使用索引?

    索引是存储引擎用于快速查找记录的一种数据结构,我们可以通过合理的使用数据库索引以提高数据库的访问效率.接下来主要介绍在MySQL 数据库中索引类型,以及如何创建出更加合理且高效的索引技巧. MySQL ...

  2. SQL Server聚集索引的选择

    先声明文章非原创,摘自博客园:http://www.cnblogs.com/CareySon/archive/2012/03/06/2381582.html 简介    在SQL Server中,数据 ...

  3. 第6/24周 聚集索引

    上个星期我向你介绍了堆表(heap tables).我们说过,在SQL Server表可以是堆表(Heap Table)或者聚集表(Clustered Table)--一个在它上面有聚集索引(Clus ...

  4. mysql 堆表_Mysql聚集索引和非聚集索引(堆组织表和索引组织表)

    Mysql聚集索引和非聚集索引(堆组织表和索引组织表) 1.堆组织表(HOT)和索引组织表(IOT)有什么区别? myisam使用的堆组织表(Heap Organize Table, HOT),没有聚 ...

  5. 聚集索引与非聚集索引及其查询效率【转载】

    摘自:http://www.cnblogs.com/myaspnet/archive/2011/06/16/2082667.html 在以下的文章中,我将以"办公自动化"系统为例, ...

  6. 聚集索引和非聚集索引详解 (zhuang)

    SQL中.聚集索引和非聚集索引有何区别? 聚集索引和非聚集索引的根本区别是表记录的排列顺序和与索引的排列顺序是否一致,聚集索引表记录的排列顺序与索引的排列顺序一致,优点是查询速度快,因为一旦具有第一个 ...

  7. Mysql聚集索引和非聚集索引(堆组织表和索引组织表)

    1.堆组织表(HOT)和索引组织表(IOT)有什么区别? myisam使用的堆组织表(Heap Organize Table, HOT),没有聚集索引的概念,使用B-tree索引的存储格式,显示都是随 ...

  8. 为什麽我们一般会在自增列或交易时间列上建立聚集索引

     为什麽我们一般会在自增列或交易时间列上建立聚集索引? 到新公司上班也有一段时间了,感觉现在的自己才开始慢慢学习SQL~ 看这篇文章之前,大家可以先看一下我之前写的一篇文章 聚集索引表插入数据和删 ...

  9. 唯一聚集索引上的唯一和非唯一非聚集索引

    在上篇文章里,我讨论了唯一和非唯一聚集索引的区别.我们已经知道,SQL Server内部使用4 bytes的uniquifier来保证非唯一聚集索引行唯一.今天我们来看下唯一聚集索引上,唯一和非唯一非 ...

最新文章

  1. 包邮免费送2022年科研人专属趣味台历,微科盟年终福利,错过悔一年!
  2. 【Codeforces 922D】Robot Vacuum Cleaner
  3. Seleunim 获取文本和标签属性的方法
  4. C++(八)——文件操作
  5. 快速得到栈、队列的最大值
  6. 上海大华条码称代码_银豹收银之大华条码秤传称设置
  7. java-网络编程篇
  8. ansi-html Uncontrolled Resource Consumption in ansi-html报错解决
  9. 用java编写汽车_java,编写一个汽车类
  10. android输入法横向,Android 手机拼音输入法横向全评
  11. 人生的苦难需要时间去磨练
  12. Android设备刷Device-owner说明
  13. 2-5暴力破解防范措施和防范误区
  14. 微信小程序base64转为二维码、条形码图片
  15. HNUST OJ 2292 烟花易逝
  16. NVIDIA Tegra Xavier 刷机以及pytorch安装
  17. 漫画制作软件Comic Strip Factory Mac
  18. 密码学DAY1_02
  19. 《鲸鱼安慰了大海》精选篇章
  20. 云原生:打造「阿拉丁神灯式」应用厨房

热门文章

  1. virus.win32.xorer病毒
  2. 17R-无重复数字的三位数和去重后最大数
  3. Mac上显示出.m2文件夹并将IDEA中的Maven修改为阿里云镜像
  4. python程序30行_Python30行代码实现对pdf文字内容的提取
  5. 测试面试题集-Linux常用命令
  6. Mac上的IDEA安装配置maven
  7. 波卡跨链交易协议RAI Finance将接入Bounce Finance实现IDO代币发行
  8. SAP License:生产订单结算时候的几个差异
  9. SAP License:如何预防企业“癌症”
  10. 实操|风控规则的监控与自动化策略生成