第6周 聚集索引

原文:第6周 聚集索引

上个星期我向你介绍了堆表(heap tables)。我们说过,在SQL Server表可以是堆表(Heap Table)或者聚集表(Clustered Table)——一个在它上面有聚集索引(Clustered Index)定义的表。今天我们来谈论聚集索引(Clustered Index)的更多细节,还有如何选择正确的聚集键(Clustered Key)。

每次你在SQL Server创建一个主键约束(Primary Key constraint),这个约束(默认情况)是通过唯一聚集索引(Unique Clustered Index)来执行的。这意味着你选择的那列(或多列,当你定义复合主键(composite primary key)时)必须是唯一值。作为一种副作用,你的表数据是按那列(或那些列)物理排序的。让我们一起看下在SQL Server里聚集索引(Clustered Index)的优点和缺点。

优点

聚集表最大的优点是,数据是在你的存储子系统里是按聚集键(Clustered Key)物理排序的。你可以拿传统电话本与聚集表(Clustered Table)做比较:电话本是按姓来聚合排序的,这意味着Aschenbrenner排在Bauer之前,Bauer排在Meyer之前。因此聚集表(Clustered Table)和堆表(heap tables)完全不一样,堆表没有物理上的排序顺序。

你可以从聚集表(Clustered Table)获得真正的巨大受益。想象下你在便利查找一条具体的记录,在WHERE语句里那列是你用来限制你数据的主键(Clustered Key)。在那个情况下,SQL Server在执行计划里会选择聚集索引(Clustered Index Seek)查找运算符。查找运算符会非常,非常高效,因为SQL Server使用B-tree结构来找相关的数据。这个查找运算符的复杂度总是O(log N)。如果你想学习更多关于B+tree在内部是如何使用的,你可以观看我关于这个话题的SQL Server Quickie。在过去的2010年里,我也写了关于这个话题的很多博客帖子。

当你在电话本找名为Aschenbrenner的号码是一样的,你知道那个名只能在电话本的开头部分找到,因为电话本是按这个数据(名)排序的。因此你可以避免整个电话本的扫描,而SQL Server可以避免在叶子节点聚集索引(Clustered Index)的完全扫描。

只要在你的聚集索引(Clustered Index)里没有索引碎片(index fragmentation),当你使用扫描运算符访问聚集索引时,你会使用循序存取(sqquential I/O)。索引碎片(index fragmentation)指的是你在叶节点里的页,逻辑上和物理上的排列顺序是不一样的。你可以通过Index RebuildIndex Reorganized操作来修复索引碎片(index fragmentation)。在第24周,当我们涉及数据库维护时,我们会谈到这2个操作间的区别。

是否有索引碎片取决于你选择的聚集键(Clustered Key)列。只要你使用自增长值(像 INT IDENTIY,或订单日期(OrderDate)列),记录插在聚集索引(Clustered Index)的末端。这意味着在你索引里,碎片不会被引入。因为SQL Server只在你聚集索引(Clustered Index)末端追加数据。但在一些极少的情况下,也会产生索引碎片(index fragmentation)。因此我们现在会谈到聚集索引(Clustered Index)拥有的缺点,还有聚集键(Clustered Key)的错误选择。

缺点

数据只插在聚集索引(Clustered Index)的末端会引入被称为最后页插入加锁竞争(Last Page Insert Latch Contention)的问题,因为在你的聚集索引(Clustered Index)的末端你只有一个热区(hotspot),那里各个查询在遍历(traversing through)B-tree结构时互相竞争。下图演示了这个现象。

 

为了克服这个问题,你可以选择随机聚集键(random Clustered Key)作为你的聚集索引(Clustered Index),那样的话,你就可以把插入的数据散步到聚集索引(Clustered Index)里各个不同地方。但是随机聚集键(random Clustered Key)会引入被称为硬页分裂(Hard Page Splits)的问题,因为SQL Server需要把新数据页分配到在聚集索引(Clustered Index)叶子级别之内的一些地方。硬页分裂(Hard Page Splits)同样也有在事务日志(transaction log)性能上的负面影响,因为相比在你聚集索引(Clustered Index)末端记录一个普通的INSERT(被称为软页分裂(Soft Page Splits)),记录一个硬页分裂(Hard Page Splits)需要更多的工作。

作为一个副作用,随机聚集键(random Clustered Key)会引入索引碎片(index fragementation),因为你的逻辑和物理排列顺序已经不再一样。随机存取(random I/O) 会扼杀你在传统的旋转存储的扫描操作性能,因为当读取各个数据页的时候,磁头必须在硬盘的盘片上前后移动。

小结

聚集索引(Clustered Index)伸缩性(scale)很好,因为它内部采用了B-tree数据结构。当在你表进行索引查找(index seek)运算符时,SQL Server可以很高效的利用这个结构。但是选择一个正确并合适的聚集键(Clustered Key)是个很耗时的工作,因为你要考虑每个情况下所有优点和缺点(什么时候用增值型(increasing value),什么时候用随机值型(random value))。

(作者广告时间,推销自己额外详细介绍如何选择正确和合适的列作为聚集键超长1个多小时视频,清仓打折出售,买2得3,不翻译。)

下星期我会谈论SQL Server里非聚集索引(Non-Clustered Indexes)的更多信息。你会学到什么是非聚集索引(Non-Clustered Indexes),还在聚集索引(Clustered Indexe)里定义的聚集键(Clustered Key),非聚集索引(Non-Clustered Indexes)与它有怎样的从属关系。好好享受接下来的7天,到时候我们会再次见面。

时间: 2024-08-03 02:18:50

第6周 聚集索引的相关文章

[翻译] 聚集索引表 VS 堆表

问题描述      创建一个新表时,一个非常重要的设计原则就是创建还是不创建聚集索引的决定.没有聚集索引的表被称为堆,拥有聚集索引的表叫聚集索引表. 聚集索引表比堆表拥有一些好处(优势),比如聚集索引表是基于聚集索引键顺序存储的,正因为如此,所以通过聚集索引可以快速查找某一行:可以通过重建聚集 索引重新组织数据.当你对表进行INSERT.UPDATE.DELETE等操作时可能会使物理数据变得碎片化,这种碎片化可能会导致你浪费大量数据库存 储空间,因为本来可以存储在一页的数据,需要存储在多个数据页

SQL Server 2014的可更新列存储聚集索引新特性探秘

简介 列存储索引其实在在SQL Server 2012中就已经存在,但SQL Server 2012中只允许建立非聚集列索引,这意味着列索引是在原有的行存储索引之上的引用了底层的数据,因此会消耗更多的存储空间,但2012中的限制最大的还是一旦将非聚集列存储索引建立在某个表上时,该表将变为只读,这使得即使在数据仓库中使用列索引,每次更新数据都变成非常痛苦的事.SQL Server 2014中的可更新聚集列索引则解决了该问题. 可更新聚集列存储索引? 聚集列存储索引的概念可以类比于传统的行存储,聚集

从性能的角度谈SQL Server聚集索引键的选择

简介 在SQL Server中,数据是按页进行存放的.而为表加上聚集索引后,SQL Server对于数据的查找就是按照聚集索引的列作为关键字进行了.因此对于聚集索引的选择对性能的影响就变得十分重要了.本文从旨在从性能的角度来谈聚集索引的选择,但这仅仅是从性能方面考虑.对于有特殊业务要求的表,则需要按实际情况进行选择. 聚集索引所在的列或列的组合最好是唯一的 这个原因需要从数据的存放原理来谈.在SQL Server中,数据的存放方式并不是以行(Row)为单位,而是以页为单位.因此,在查找数据时,S

SQL Server 2008存储结构之非聚集索引

非聚集索引与聚集索引具有相同的 B 树结构,它们之间的显著差别在于以下两点: 基础表的数据行不按非聚集键的顺序排序和存储. 非聚集索引的叶层是由索引页而不是由数据页组成. 非聚集索引既可以建在堆表结构上也可以建在聚集索引表上:非聚集索引中的每个索引行都包含非聚集键值和行定位符.此定位符指向聚集索引或堆中包含该键值的数据行. 如果表是堆则行定位器是指向行的指针.该指针由文件标识符 (ID).页码和页上的行数生成.整个指针称为行 ID (RID). 如果表包含有聚集索引,则行定位器是行的聚集索引键.

主键和聚集索引和单列索引和多列索引

  1. 主键与聚集索引 首先澄清一个概念,主键并不等于聚集索引.(这不是废话么,如果是同一个东西,微软也不会叫两个不同的名字了) 一个表只能有一个聚集索引,数据在物理上是按照聚集索引的顺序来存放的. 主键分为聚集的主键和非聚集的主键.默认是聚集的主键.下面代码是SqlServer自动生成的CREATE TABLE 代码,注意设定主键那句话中的' CLUSTERED',即表示聚集的主键. /****** Object: Table [dbo].[User] Script Date: 03/28/

聚集索引和非聚集索引

  聚集索引 一种索引,该索引中键值的逻辑顺序决定了表中相应行的物理顺序. 聚集索引确定表中数据的物理顺序.聚集索引类似于电话簿,后者按姓氏排列数据.由于聚集索引规定数据在表中的物理存储顺序,因此一个表只能包含一个聚集索引.但该索引可以包含多个列(组合索引),就像电话簿按姓氏和名字进行组织一样. 聚集索引对于那些经常要搜索范围值的列特别有效.使用聚集索引找到包含第一个值的行后,便可以确保包含后续索引值的行在物理相邻.例如,如果应用程序执行 的一个查询经常检索某一日期范围内的记录,则使用聚集索引可

PostgreSQL 10.0 preview 功能增强 - OLAP增强 向量聚集索引(列存储扩展)

标签 PostgreSQL , 10.0 , Vertical Clustered Index (columnar store extension) , 列存储 , 向量聚集索引 背景 未来数据库OLTP+OLAP逐渐模糊化,需求逐渐融合是一个大的趋势,如果你的数据库只支持OLTP的场景,未来可能会成为业务的绊脚石. 在这方面PostgreSQL每年发布的新版本,都给用户很大的惊喜,OLTP已经具备非常强大的竞争力(性能.功能.稳定性.成熟度.案例.跨行业应用等),而OLAP方面,新增的feat

SQLSERVER聚集索引与非聚集索引的再次研究(上)

原文:SQLSERVER聚集索引与非聚集索引的再次研究(上) SQLSERVER聚集索引与非聚集索引的再次研究(上) 上篇主要说聚集索引 下篇的地址:SQLSERVER聚集索引与非聚集索引的再次研究(下) 由于本人还是SQLSERVER菜鸟一枚,加上一些实验的逻辑严谨性, 单写<SQLSERVER聚集索引与非聚集索引的再次研究(上)>就用了12个小时,两篇文章加起来最起码写了20个小时, 本人非常非常用心的努力完成这两篇文章,希望各位看官给点意见o(∩_∩)o   为了搞清楚索引内部工作原理和

索引键的唯一性(1/4):堆表上的唯一与非唯一非聚集索引的区别

原文:索引键的唯一性(1/4):堆表上的唯一与非唯一非聚集索引的区别 在这篇文章里,我想详细介绍下SQL Server里唯一与非唯一非聚集索引的区别.看这个文章前,希望你已经理解了聚集和非聚集索引的概念,还有在SQL Server里是如何使用的. 很多人对唯一和非唯一索引非聚集索引的认识都不是很清晰.事实上,SQL Server在存储上这2类索引有着本质的区别,这些区别会影响到索引占用空间的大小和索引的使用效率. 今天我们从SQL Server里的堆表(Heap table) ,它是没有聚集索引