前言: 本文对这篇博客Clustered Tables vs Heap Tables 的翻译, 如有翻译不对或不好的地方,敬请指出,大家一起学习进步。

问题描述

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

解决方案

我们要解决的首要问题是发生在数据库正常活动中的碎片。你的表是否拥有聚集索引 将决定您是否可以在数据库物理层面很容易的解决碎片化问题。因为堆或聚集索引决定你表数据的物理存储,每个表要么拥有一个聚集索引或没有一个聚集索引,所以每个表要么是一个堆或聚集索引表。

让我们来看看一个堆表和聚集索引表之间的差异:

HEAP

数据存储没有任何特定的顺序。

不能快速的找到特定数据,除非也有非聚集索引。

数据页之间没有指针关联,所以顺序访问需要重新返回到索引分配映射(IAM)页

既然没有聚集索引,所以不用额外的时间去维护聚集索引。

既然没有聚集索引,所以不用额外的空间去存储聚集索引树。

堆表的索引在sys.indexes目录视图的记录的index_id字段值为0

Clustered Table

数据存储基于聚集索引键顺序存储。

如果查询时使用聚集索引列,数据可以基于聚集索引键快速检索到。

数据页之间有指针链接,可以更快速的顺序访问。

当INSERT、UPDATE、DELETE操作时,需要额外的时间维护聚集索引。

需要额外的空间存储聚集索引树。

聚集索引表在sys.indexes目录视图的记录的index_id值为1.

所以,基于以上你可以看到有一个表是否具有聚簇索引将决定表的一些根本性的不同之处。

碎片化问题

所有的表都会发生的一个问题就是碎片化的问题。根据不同的操作,比如删除,插入和更新,您的堆表和聚集索引表将会变得越来越碎片化。碎片化很多时候取决于INSERT、UPDATE、DELTE这类操作,以及用作聚集索引的键。

如果您的堆表只有INSERT操作,你的表不会变得碎片化,因为只有新的数据写入。

如果您的聚集索引键是连续的,比如一个自增字段。并且对该表你只有INSERT操作,这同样也不会变得碎片化,因为新的数据总是写在聚簇索引的后面。

但是,如果你的表是一个堆或聚集表,并有大量的插入,更新和删除操作,数据页碎片化可能会变得越来越严重。这不仅会导致浪费额外的空间,而且需要读取额外的数据页来满足查询。

当一个表在堆上创建,SQL Server不会强迫在那个新数据页(New Page)写入数据。每当新的数据写入时,该数据总是写在表的末端,或者分配给该表中的下一个可用的页面上。当数据被删除时,数据页上的空间释放出来,但它不重复使用,因为新数据总是写入到下一个可用的页面。

具有聚簇索引,根据索引键,新的记录可能会被写入到现有的页面,这些页面可能存在的空闲的空间或者有可能需要分割成多个页面的页面。以便插入新的数据。删除时会发生同样的问题时,与一个堆对比,但是这些空闲间可以再次使用,如果数据需要插入到具有可用空间的现有页面中的一个。

所以,基于以上叙述 ,你的堆表可能变得比你的聚集表更加支离破碎。

查看碎片化
要确定您的聚集索引表或堆表是否碎片化,你要么通过运行DBCC SHOWCONTIG(SQL SEREVER 2000或SQL SEREVER 2005)查看,或使用新的DMVsys.dm_db_index_physical_stats(SQL SERVER 2005 以及以后版本)。这些命令能让你查看表中可能存在的碎片化问题。如需更多相关信息,看看以前的这篇文章提示:SQL Server 2000 to 2005 Crosswalk - Index Rebuilds.

解决碎片化

聚集索引表


    解决聚集索引的碎片化可以很容易地通过重建或重新组织你的聚集索引来完成。这表现在这之前的提示: SQL Server 2000 to 2005 Crosswalk - Index Rebuilds

堆表

对于堆表来说,这个不太容易的。您可以采取以下不同的方法来解决碎片问题:

  1. 对堆表创建一个聚集索引
  2. 创建一个新的堆表,并根据某种顺序将旧表中的数据插入到新表
  3. 导出数据,截断表并导入数据返回到表

附加信息

当你通过企业管理器或Management Studio创建一个新表并在新表中指定一个主键,管理工具会自动为其创建一个聚集索引,但可以被重写。当通过脚本创建一个新表时,你需要明确指定创建聚集索引。所以,正是由于主键关系,你大部分的表将会拥有一个聚集索引,但如果创建表时,你不指定一个主键或建立聚集索引,该表的数据将被存储为一个堆。

 

下一步

维持表和索引的碎片化在控制范围内是保持数据库最佳性能的一个关键过程。现在你可以明白一个堆与聚集索引表在解决碎片化上的不同,看看你的表结构,看看你需要解决这些问题。

即使对所有表一个星期做一次索引重建,你的堆表是永远不会解决琐碎化问题的,所以你需要想出另一种策略来处理堆表的碎片问题。

一起来看看这些相关技巧:

SQL Server 2000 to 2005 Crosswalk - Database Fragmentation.

SQL Server 2000 to 2005 Crosswalk - Index Rebuilds.

基于上述论证,似乎所有的表都应该有一个聚集索引。在大多数情况下是这样,但也可能由于某种原因,你不希望有一个聚集索引。一个原因可能是该表只有INSERT操作,例如一个日志记录的表。但是毫无疑问,有聚集索引一定好过没有聚集索引

[翻译] 聚集索引表 VS 堆表的更多相关文章

  1. 索引深入浅出(4/10):非聚集索引的B树结构在聚集表

    一个表只能有一个聚集索引,数据行以此聚集索引的顺序进行存储,一个表却能有多个非聚集索引.我们已经讨论了聚集索引的结构,这篇我们会看下非聚集索引结构. 非聚集索引的逻辑呈现 简单来说,非聚集索引是表的子 ...

  2. SQL SERVER中关于OR会导致索引扫描或全表扫描的浅析

    在SQL SERVER的查询语句中使用OR是否会导致不走索引查找(Index Seek)或索引失效(堆表走全表扫描 (Table Scan).聚集索引表走聚集索引扫描(Clustered Index ...

  3. SQL Server 堆表与栈表的对比(大表)

    环境准备 使用1个表,生成1000万行来进行性能对比(勉强也算比较大了),对比性能差别. 为了简化过程,不提供生成随机数据的过程.该表初始为非聚集索引(堆表),测试过程中会改为聚集索引(栈表). CR ...

  4. SQL Server性能优化(8)堆表结构介绍

    一.表结构综述 下图是SQL Server中表的组织形式(其中分区1.分区2是为了便于管理,把表进行分区,放到不同的硬盘数据文件里.默认情况下,表只有一个分区.).表在硬盘上的存放形式,有堆和B树两种 ...

  5. SQL SERVER中关于OR会导致索引扫描或全表扫描的浅析 (转载)

    在SQL SERVER的查询语句中使用OR是否会导致不走索引查找(Index Seek)或索引失效(堆表走全表扫描 (Table Scan).聚集索引表走聚集索引扫描(Clustered Index ...

  6. SQL SERVER大话存储结构(2)_非聚集索引如何查找到行记录

              如果转载,请注明博文来源: www.cnblogs.com/xinysu/   ,版权归 博客园 苏家小萝卜 所有.望各位支持!      1 行记录如何存储     这里引入两个 ...

  7. 索引深入浅出(5/10):非聚集索引的B树结构在堆表

    在“索引深入浅出:非聚集索引的B树结构在聚集表”里,我们讨论了在聚集表上的非聚集索引,这篇文章我们讨论下在堆表上的非聚集索引. 非聚集索引可以在聚集表或堆表上创建.当我们在聚集表上创建非聚集索引时,聚 ...

  8. SQL Server 索引和表体系结构(聚集索引)

    聚集索引 概述 关于索引和表体系结构的概念一直都是讨论比较多的话题,其中表的各种存储形式是讨论的重点,在各个网站上面也有很多关于这方面写的不错的文章,我写这篇文章的目的也是为了将所有的知识点尽可能的组 ...

  9. SQL Server索引 (原理、存储)聚集索引、非聚集索引、堆 <第一篇>

    一.存储结构 在SQL Server中,有许多不同的可用排列规则选项. 二进制:按字符的数字表示形式排序(ASCII码中,用数字32表示空格,用68表示字母"D").因为所有内容都 ...

随机推荐

  1. 1Z0-053 争议题目解析681

    1Z0-053 争议题目解析681 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 681.The environmental variable ORACLE-BASE is set ...

  2. CSS中对图片(background)的一些设置心得总结

    写网页的时候很多情况需要对图片进行操作,如何在不进行专业的美工裁切操作的情况下而让自己的素材度达到最大的满意度呢,这是一个问题,对于懒得开ps切图的我,通常会直接在网络上download一张图片,直接 ...

  3. ASP.NET MVC 概述

    目标:学习ASP.NET MVC 和ASP.NET WebForm的不同之处.学习在合适的地方使用ASP.NET MVC. MVC(Model-View-Controller)结构模式把一个对象分离成 ...

  4. 【LeetCode】Reconstruct Itinerary(332)

    1. Description Given a list of airline tickets represented by pairs of departure and arrival airport ...

  5. springmvc4环境简单搭建和定时任务

    之前复制粘贴创建了几个ssm的项目,然而回头让自己写的时候还是一头雾水,究其原因是spring的陌生.仅仅是写过几个helloworld而已.而且是照着写.我都不知道springmvc到底需要多少ja ...

  6. Java进击C#——项目开发环境

    本章简言 上一章我们了解一下开发环境,知道了什么去新建一个项目工程.却并没有去项目工程进行介绍.可是之后我们会常常跟项目工程打交道.所以这章笔者就对项程工程的常用的一些功能进行讲解.当然说全面那是不可 ...

  7. C#获取图片的后缀名

    最近在学习过程中遇到一个问题,就是如何获取图片的格式,对于一张知道全路径的照片,如果其路径包含后缀名的话,要取得后缀名,只需要一行代码即可: var ext = System.IO.Path.GetE ...

  8. WPF模糊效果(BlurEffect)

    <TextBlock Padding="10" Text="设置模糊" FontSize="32" Background=" ...

  9. [WCF编程]12.事务:服务事务编程(上)

    一.设置环境事务 默认情况下,服务类和操作没有环境事务,即使客户端事务传播到服务端也是如此. 尽管强制事务流从客户端传播过来,但服务端的环境事务依旧为null.为了启用环境事务,每个操作必须告诉WCF ...

  10. ftp 根据特定正则匹配文件名 下载到本地 并且上传文件到ftp java *** 最爱那水货

    /** * 建立FTP链接,FTP服务器地址.端口.登陆用户信息都在配置里配置即可. * @throws IOException */ public boolean connectFtp(String ...