堆压缩


14

以下是Microsoft Docs的一段:

在DML操作中分配给堆中的新页面在重建堆之前不会使用PAGE压缩。通过删除和重新应用压缩,或通过创建和删除聚簇索引来重建堆。

我不知道为什么会这样。如果我的堆具有指定的压缩设置,为什么不将其应用于属于该表的页面?

谢谢

Answers:


12

虽然我不知道造成这种差异的具体内部机制,但我可以说,堆的管理(内部)与聚簇索引(可能还包括非聚簇索引)略有不同:

  • 从堆中删除行以使一个或多个数据页为空(没有分配的行)不一定会释放该空间。您可能需要在表上创建然后删除聚簇索引,或者进行调用ALTER TABLE [TableName] REBUILD;(从SQL Server 2014开始)。有关更多详细信息和选项,请参阅Microsoft文档页面以进行DELETE

  • 将单个行(即不是基于集合的行INSERT)插入到堆中不会像使用聚集索引那样完全填充数据页。只要该行有空间(数据和行开销)加上插槽数组的2字节开销,聚集索引将适合行。但是,堆中的数据页不使用页面上剩余的字节数,而是使用非常笼统的指示符来指示页面的填充程度,并且报告的层数并不多。级别大致为:0%,20%,50%,80%和100%充满。并且它将切换到100%,同时还有另一行的空间(实际上,如果在基于集合的操作中插入了相同数量的行,则它将尽可能多地填满页面)。当然,就像DELETE 操作,重建堆将打包到数据页面上的尽可能多的行。

现在考虑以下信息,取自“当页面压缩发生”为微软文档页面的部分页面压缩实现

...当数据添加到第一个数据页时,数据将进行行压缩。...当页面已满时,要添加的下一行将启动页面压缩操作。整个页面都经过审查;...

因此,这似乎完全符合此其他堆行为,即在写入数据页之前,它们将需要ALTER TABLE REBUILD,CREATE / DROP聚集索引或更改Data Compression设置(所有这些都重建堆)。最佳。如果堆不完全了解“整个页面”(直到重建堆)并且不知道页面何时肯定已满,那么他们将不知道何时启动页面压缩操作(在处理更新和单个操作时)。 -行插入)。

另一个会进一步限制某些堆无法自动应用页面压缩的技术(即使可能的话)是,应用压缩将需要重建该堆的所有非聚集索引(如果存在)。正如该链接的“数据压缩”页面还指出:

更改堆的压缩设置需要重建表上的所有非聚集索引,以便它们具有指向堆中新行位置的指针。

所指的“指针”是行ID(RID),它们是以下各项的组合:FileID,PageID和页面上的插槽/位置。这些RID被复制到非聚簇索引中。作为精确的物理位置,与使用聚簇索引键遍历b树相比,它们有时查找速度更快。但是,物理位置的一个缺点是它可以更改,这就是这里的问题。但是,聚簇索引不会遇到此问题,因为它们的键值作为指向聚簇索引的指针被复制到非聚簇索引中。而且,即使键值的物理位置发生变化,键值也保持不变。

另请参阅:

  • Microsoft文档页的“管理堆”部分中的堆(不带聚集索引的表)

    要重建堆以回收浪费的空间,请在堆上创建一个聚集索引,然后删除该聚集索引。

  • Microsoft Docs页面用于数据压缩的 “使用行和页面压缩时的注意事项”部分:

    当将堆配置为页面级压缩时,页面仅通过以下方式获得页面级压缩:

    • 启用批量优化后,批量导入数据。
    • 使用INSERT INTO ... WITH(TABLOCK)语法插入数据,并且该表没有非聚集索引。
    • 通过使用PAGE压缩选项执行ALTER TABLE ... REBUILD语句来重建表。

    问题中引用的陈述。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.