【问题标题】:SQL Server - Why Alter Table Adding Nullable Columns to a Table causes a RebuildSQL Server - 为什么更改表向表中添加可为空的列会导致重建
【发布时间】:2020-11-03 06:20:32
【问题描述】:

我们有一个 250GB 的数据库,其中包含一个 180GB 的表(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 ;

我们过去使用相同的方法在此表中添加了 75 个列,并且只用了几秒钟。这一次,在弹性 Azure 池 (800 EDTU) 中,我将 DB 最大大小设置为 500GB,但在运行上述查询 6 小时 后空间不足

这似乎是在后台间接重建表或更多(即使这是一个不涉及直接复制表的 TSQL 调用) - 更奇怪的是,即使它重建了表,为什么它需要更多比另一个 ~180 GB(即 250 GB + 另一个 180 GB 应该小于 500 GB)

注意:这些不是具有任何默认值或上面未显示的任何其他内容的索引列

我很想知道这是否是预期的行为。是否存在将可空列添加到表末尾会触发重建的任何条件,如果是,是什么条件强制执行此操作,为什么它比原始表消耗更多?

【问题讨论】:

  • 看看那些列名让我畏缩 - 你应该使用正确的关系建模 - 而不是这样的 - 这违反甚至关系数据库设计的第一范式!
  • @marc_s 这并不是一个规范化的表格。它的意思是完全相反的。

标签: sql-server azure-sql-database alter-table


【解决方案1】:

如果行宽的总和大于页面大小(大约 8KB),则可能需要做一些工作来尝试让您的架构适合页面。固定大小的字段,例如浮动,在所有情况下都需要在页面上。 SQL 确实具有获取一些可变大小字段并在某些情况下将它们放在行外的功能。这可能是 sizeof(data) 操作的原因,尽管这实际上只是猜测,没有完整的重现。

可能发生的情况是 DDL 操作需要修改所有行才能完成操作。它不是“重建”,因为您将通过构建一个新索引并将所有数据移至该索引来重建索引。 SQL 确实具有尽可能“在线”模式操作的逻辑,这意味着如果我们可以避免执行 sizeof(data) 操作,我们就会这样做。这包括添加未定义默认值的列(因此我们不必触摸表中的所有现有行来为这些现有行设置新的默认值)。但是,对此有一些限制。请参阅此页面上的 WITH(ONLINE=ON) 语法的在线文档:

https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql?view=sql-server-ver15

【讨论】:

  • 拥有多个使用相同结构的环境 - 我们的结果不一致,其中一些会立即发生,而另一些则强制执行某种全表操作。
  • SQL 有两层元数据——我们称它们为“RE”(关系引擎)和“SE”(存储引擎)。在添加/删除操作的情况下,底层可能与上层略有不同。当您在添加导致 sizeof(data) 操作的列时达到限制时,这可能会产生潜在影响。 with online=on 选项应该让您在需要 sizeof(data) 的情况下通过快速失败来捕捉这些变化,以便您可以安排在下班时间或考虑替代模型进行调整
猜你喜欢
  • 1970-01-01
  • 2020-01-29
  • 2012-04-20
  • 2013-10-31
  • 1970-01-01
  • 2017-07-02
  • 2017-01-07
  • 2017-03-28
  • 1970-01-01
相关资源
最近更新 更多