填充因子是如何物理分配的?

时间:2009-09-02 13:02:27

标签: sql-server sql-server-2005 sql-server-2000 fillfactor

我一直在网上搜索图书和谷歌咒语试图找出一个页面中的填充因子(SQL Server 2000和2005)。

据我所知,创建索引时页面上剩余空间的数量是多少,但我找不到的是 这个空间实际上是什么?就是说,它是一个大的在页面末尾的块,或者是通过该数据的几个间隙。

例如,[只是为了保持简单],假设一个页面只能容纳100行。如果填充因子被指定为75%,这是否意味着页面的第一个(或最后一个)75%是数据而其余部分是免费的,是每四行免费(即,页面看起来像:数据,数据,数据,免费,数据,数据,数据,免费,......)。

这样做的长短之处在于,我正在准确处理在将行插入具有聚簇索引的表中时发生的物理操作所发生的事情,并且插入不会发生在最后排。如果在页面中留下多个间隙,则插入对影响最小(至少在页面拆分之前),因为可能需要移动以容纳插入的行数最小化。如果差距在表中的一个大块中,则处理周围行的开销(理论上至少)会明显更多。

如果有人知道MSDN参考,请指点我!我现在找不到一个(尽管仍在寻找)。从我所读到的暗示它有很多空白 - 但这似乎没有明确说明。

2 个答案:

答案 0 :(得分:2)

来自MSDN

  

填充因子设置仅在创建或重建索引时适用。 SQL Server Database Engine不会动态保留页面中指定的空白百分比。尝试维护数据页面上的额外空间会破坏填充因子的目的,因为Database Engine必须执行页面拆分,以便在输入数据时保持每页上填充因子指定的可用空间百分比。

并且,进一步:

  

当一个新行添加到完整索引页面时,Database Engine将大约一半的行移动到新页面,以便为新行腾出空间。这种重组称为页面拆分。页面拆分为新记录腾出空间,但可能需要一段时间才能执行,并且是一项资源密集型操作。此外,它可能导致碎片,导致I/O操作增加。当频繁页面拆分发生时,可以使用新的或现有的填充因子值重建索引以重新分配数据。

SQL Server的数据页面包含以下元素:

  • Page header96字节,已修复。
  • Data:变量
  • Row offset array:变量。

行偏移数组始终存储在页面的 end 中,并向后增长

数组的每个元素都是2 - 字节值,将偏移量保存到页面中每行的开头。

行不在数据页中排序:相反,它们的顺序(在集群存储的情况下)由行偏移数组确定。这是排序的行偏移量。

比如说,如果我们将一个100字节行的群集密钥值10插入到一个群集表中并进入一个空闲页面,它将被插入如下:

[00   - 95   ]   Header
[96   - 195  ]   Row 10
[196  - 8190 ]   Free space
[8190 - 8191 ]   Row offset array: [96]

然后我们在同一页面中插入一个新行,这次使用群集键值9

[00   - 95   ]   Header
[96   - 195  ]   Row 10
[196  - 295  ]   Row 9
[296  - 8188 ]   Free space
[8188 - 8191 ]   Row offset array: [196] [96]

该行预先在逻辑上但附加在物理上。

重新排序偏移数组以反映行的逻辑顺序。

鉴于此,我们可以很容易地从页面的开头看到行附加到空闲空间,而指向行的指针预先到从页面末尾开始的自由空间。

答案 1 :(得分:0)

这是我第一次想到这一点,我对结论不是肯定的,但是,

由于SQL Server在单个读取IO中可以检索的最小数据量是一个完整的数据页面,为什么单个页面中的任何行都需要首先进行排序?我敢打赌,他们不是,所以即使差距在最后都有一个很大的差距,最后可以添加新记录,无论这是否是正确的排序顺序。 (如果没有理由首先在页面上对记录进行排序)

其次,考虑到IO的写入方面,我认为最小的写入块也是整个页面,(即使是最小的更改也需要将整个页面写回磁盘)。这意味着每次页面写入时页面上的所有行都可以在内存中进行排序,因此即使您在dingle页面上插入有序行集的开头,整个页面也会被读出,可以将新记录插入到内存中设置的正确插槽中,然后将整个新排序的页面写回磁盘......