将列添加到表时,SQL Server 中的“行链接/溢出”?

d-_*_*_-b 5 sql-server sql-server-2012

表中的每一行可以是 8060 字节,因为页面大小是 8KB。如果行大小超过此值,最大的列将移动到另一个页面ROW_OVERFLOW_DATA并在原始页面上创建一个指针。

将新列添加到现有表时会发生什么?数据是否存储在表的“末尾”,并且在页面中的每个现有行之后创建指针以指向这个新数据?显然这会导致性能问题..

还是整个表格都经过重新组织,以便新列“适合”原始页面?

我们正在运行 SQL 2012(及更高版本)企业版,但也有兴趣了解较低版本。我对堆和聚集索引都感兴趣,因为在任何一个中,必须修改现有行 - 添加新列,或添加指向新列的指针,对吗?

Joe*_*ish 7

这里有三个独立的概念,我认为将它们分开很重要。

1.在表中添加一列

向表中添加列是一种优化操作,旨在不占用大量时间。大多数情况下,它不需要修改表中的所有页面。您可以通过测量执行此操作所需的事务大小或查看表前后使用的空间来验证此。

假设您将一列添加到默认值为 1 的表中。该表有 1000 亿行。修改每个数据页为每一行写一个“1”真的有意义吗?这可能需要很长时间。相反,您可以以一种解决数据的方式解释数据。如果新行的值尚未写入页面,则可以假定它是默认值。

Martin Smith指出,此优化仅适用于企业版。一个经验法则是,如果列的新值不是常量,例如计算列或默认值为NEWID(). 有一些边缘情况可能会导致所有页面都被修改,例如这个

2. 更新现有行的列

如果您更新列,则整行可能不再适合数据页。对于堆,该行将通过指针移动到新页面。这称为转发记录。对于聚集索引,一些行将被移动到新页面。这被称为页面拆分,许多人已经写了大量关于它们的文章。如果一个表有如此多的转发记录和页面拆分,以至于您遇到了某种性能问题,那么可以使用REBUILD. 但你可能有更好的事情需要担心。

3. 大于 8k 的行

从 SQL Server 2008 开始,行可以大于 8k。您在问题中的链接中解释了执行此操作所涉及的一些机制。从概念上讲,这与向表中添加列几乎没有关系。

  • 您的。(1) 仅适用于 2012+ 的企业版。并且仅当默认值是运行时常量时。否则它不是在线操作并且确实修改每一行。 (3认同)