重新理解SQL Server的聚集索引表与堆表

时间:2022-02-06 08:59:09

目录

简述SQL Server表的类型

由于当前关系型数据库(RDBMS)种类繁多,存在对标准SQL(结构化查询语言)实现上存在差异,对表、索引的实现也各有不同,造成了大家对很多概念在理解上存在误差。如下将描述MS SQL Server的聚集索引表与堆表,以便大家重新理解。

SQL Server只存在2种表:

聚集索引表(Clustered table)
堆表(Heap)

简单的说,含有聚集索引(clustered index)的表即为聚集索引表,而堆表则是不含聚集索引的表。
注意:仅含有非聚集索引(Nonclustered index),而没有聚集索引(clustered index)的表是堆表

如何区分聚集索引表与堆表

通过目录视图(catalog views)sys.partitions或sys.indexes可查询表的类型:

--通过判断index_id的值,区分表的类型
--当index_id为0时,则为堆表
--当index_id为1时,则为聚集索引表
SELECT OBJECT_NAME(s.object_id) talbe_name ,CASE s.index_id WHEN 0 THEN 'heap' WHEN 1 THEN 'clustered table' END table_type FROM sys.partitions s WHERE s.index_id < 2 GROUP BY s.object_id,s.index_id

使用目录视图sys.indexes查询表的类型:

--注意:当表为堆表时,name为NULL
SELECT OBJECT_NAME(object_id) table_name, name, type_desc FROM sys.indexes WHERE index_id <2

注意:上述sql适用于所有的表。换言之,分区表也可使用上述sql进行判断

你可能好奇为何上述2个目录视图(sys.partitions或sys.indexes)可查询所有表的类型(聚集索引表或堆表),那么我们需简单描述表与索引的组织结构,见下图(图片取自《Microsoft SQL Server 2008 Internals》)

重新理解SQL Server的聚集索引表与堆表

SQL Server是通过分区去管理与组织数据记录的,且每个表至少存在一个分区,每个分区可对应一个文件组(系统默认文件组为PRIMARY)。换言之,可认为表的默认分区为PRIMARY。

聚集索引表与堆表的最大区别是:聚集索引表的数据在组织上是有序的,即聚集索引的有序性。而堆表是不含聚集索引的表。

注意:上述的组织结构是表或索引的存储结构。在SQL Server现有的版本中,还无法对表的单个分区建立索引(聚集或非聚集索引都不行)

简而言之,目录视图sys.partitions与sys.indexes均存有索引的相关信息,因此这两个视图查询聚集索引的信息,然后就可区分表的类型。

聚集索引表与堆表的正确使用

我们有很多理由去创建一个聚集索引表,而非堆表。那么最大的理由可能就是:当一个非聚集索引包含的列不能完全符合一条查询(select)时,执行计划可通过聚集索引查找,而非通过表扫描的方式。

那么我们为什么会选择堆表,原因大致就如下2点:
1. 堆表没有聚集索引,因此堆表可节省索引的磁盘空间
2. 堆表没有聚集索引,且数据组织是无序的,节省了排序操作,写入操作更快。

特别注意:在聚集索引索引表上创建分区时,务必检查sql脚本。若设置的分区函数指定的列不是聚集索引列,将会导致聚集索引的变化(删除与重建),最终导致表的类型转换。

参考资料

1.Tables and Index Data Structures Architecture
https://technet.microsoft.com/en-us/library/ms180978%28v=sql.105%29.aspx

2.《Microsoft SQL Server 2008 Internals》

3.Heaps (Tables without Clustered Indexes)
https://msdn.microsoft.com/en-us/library/hh213609.aspx