SQL 服务器 - 为什么更改 Table 添加可空列到 Table 导致重建
SQL Server - Why Alter Table Adding Nullable Columns to a Table causes a Rebuild
我们有一个 250GB 的数据库,其中包含一个 180GB Table(5500 万行或 550 列),我们通过以下方式向其添加 24 个新的空白列;
ALTER TABLE [Rpt].[tblHoldings]
ADD
[Rating01AgencyCode] VARCHAR (50) NULL,
[Rating01TypeCode] VARCHAR (50) NULL,
[Rating01Code] VARCHAR (50) NULL,
[Rating01Score] FLOAT (53) NULL,
[Rating02AgencyCode] VARCHAR (50) NULL,
[Rating02TypeCode] VARCHAR (50) NULL,
[Rating02Code] VARCHAR (50) NULL,
[Rating02Score] FLOAT (53) NULL,
[Rating03AgencyCode] VARCHAR (50) NULL,
[Rating03TypeCode] VARCHAR (50) NULL,
[Rating03Code] VARCHAR (50) NULL,
[Rating03Score] FLOAT (53) NULL,
[Rating04AgencyCode] VARCHAR (50) NULL,
[Rating04TypeCode] VARCHAR (50) NULL,
[Rating04Code] VARCHAR (50) NULL,
[Rating04Score] FLOAT (53) NULL,
[Rating05AgencyCode] VARCHAR (50) NULL,
[Rating05TypeCode] VARCHAR (50) NULL,
[Rating05Code] VARCHAR (50) NULL,
[Rating05Score] FLOAT (53) NULL,
[Rating06AgencyCode] VARCHAR (50) NULL,
[Rating06TypeCode] VARCHAR (50) NULL,
[Rating06Code] VARCHAR (50) NULL,
[Rating06Score] FLOAT (53) NULL ;
我们过去使用相同的方法为此 table 添加了 75 列,只用了几秒钟。这次在弹性 Azure 池 (800 EDTU) 中,我将数据库最大大小设置为 500GB,并且 运行 out of space after 运行以上查询 6 小时.
它似乎是在后台或更多地间接重建 table(即使这是一个不涉及直接复制 table 的 TSQL 调用)- 更奇怪的是,即使如果它重建 table 为什么它比另一个需要更多 ~180 GB(即 250GB + 另一个 180GB 应该小于 500GB)
注意:这些不是具有任何默认值或上面未显示的任何其他内容的索引列
我很想知道这是否是预期的行为。在 table 的末尾添加可空列是否有任何条件会触发重建,如果是,是什么条件强制执行此操作,为什么它比原始 table 消耗更多?
如果行宽之和大于页面大小(大约 8KB),可能需要做一些工作才能使您的架构适合页面。在所有情况下,固定大小的字段(例如浮动)都需要位于页面上。 SQL 确实具有获取某些 variable-sized 字段并在某些情况下将它们放入 off-row 的功能。这也许可以解释 sizeof(data) 操作,尽管这实际上只是没有完整重现的推测。
可能发生的情况的词汇是 DDL 操作需要修改所有行才能完成操作。它不是“重建”,因为您将通过构建新索引并将所有数据移动到其中来重建索引。 SQL 确实有逻辑,只要有可能,“在线”模式操作意味着如果我们可以避免执行 sizeof(data) 操作,我们就会这样做。这包括添加未定义默认值的列(因此我们不必修改 table 中的所有现有行来为这些现有行设置新的默认值)。但是,对此有一些限制。请参考本页WITH(ONLINE=ON)语法的在线文档:
https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql?view=sql-server-ver15
我们有一个 250GB 的数据库,其中包含一个 180GB Table(5500 万行或 550 列),我们通过以下方式向其添加 24 个新的空白列;
ALTER TABLE [Rpt].[tblHoldings]
ADD
[Rating01AgencyCode] VARCHAR (50) NULL,
[Rating01TypeCode] VARCHAR (50) NULL,
[Rating01Code] VARCHAR (50) NULL,
[Rating01Score] FLOAT (53) NULL,
[Rating02AgencyCode] VARCHAR (50) NULL,
[Rating02TypeCode] VARCHAR (50) NULL,
[Rating02Code] VARCHAR (50) NULL,
[Rating02Score] FLOAT (53) NULL,
[Rating03AgencyCode] VARCHAR (50) NULL,
[Rating03TypeCode] VARCHAR (50) NULL,
[Rating03Code] VARCHAR (50) NULL,
[Rating03Score] FLOAT (53) NULL,
[Rating04AgencyCode] VARCHAR (50) NULL,
[Rating04TypeCode] VARCHAR (50) NULL,
[Rating04Code] VARCHAR (50) NULL,
[Rating04Score] FLOAT (53) NULL,
[Rating05AgencyCode] VARCHAR (50) NULL,
[Rating05TypeCode] VARCHAR (50) NULL,
[Rating05Code] VARCHAR (50) NULL,
[Rating05Score] FLOAT (53) NULL,
[Rating06AgencyCode] VARCHAR (50) NULL,
[Rating06TypeCode] VARCHAR (50) NULL,
[Rating06Code] VARCHAR (50) NULL,
[Rating06Score] FLOAT (53) NULL ;
我们过去使用相同的方法为此 table 添加了 75 列,只用了几秒钟。这次在弹性 Azure 池 (800 EDTU) 中,我将数据库最大大小设置为 500GB,并且 运行 out of space after 运行以上查询 6 小时.
它似乎是在后台或更多地间接重建 table(即使这是一个不涉及直接复制 table 的 TSQL 调用)- 更奇怪的是,即使如果它重建 table 为什么它比另一个需要更多 ~180 GB(即 250GB + 另一个 180GB 应该小于 500GB)
注意:这些不是具有任何默认值或上面未显示的任何其他内容的索引列
我很想知道这是否是预期的行为。在 table 的末尾添加可空列是否有任何条件会触发重建,如果是,是什么条件强制执行此操作,为什么它比原始 table 消耗更多?
如果行宽之和大于页面大小(大约 8KB),可能需要做一些工作才能使您的架构适合页面。在所有情况下,固定大小的字段(例如浮动)都需要位于页面上。 SQL 确实具有获取某些 variable-sized 字段并在某些情况下将它们放入 off-row 的功能。这也许可以解释 sizeof(data) 操作,尽管这实际上只是没有完整重现的推测。
可能发生的情况的词汇是 DDL 操作需要修改所有行才能完成操作。它不是“重建”,因为您将通过构建新索引并将所有数据移动到其中来重建索引。 SQL 确实有逻辑,只要有可能,“在线”模式操作意味着如果我们可以避免执行 sizeof(data) 操作,我们就会这样做。这包括添加未定义默认值的列(因此我们不必修改 table 中的所有现有行来为这些现有行设置新的默认值)。但是,对此有一些限制。请参考本页WITH(ONLINE=ON)语法的在线文档:
https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql?view=sql-server-ver15