添加列时环境之间的性能差异

Mic*_*elD 2 performance sql-server sql-server-2019

我们有 2 个完全相同的数据库环境。第二个环境包含生产数据库的副本并在发票表中托管大约 11M 条记录。此环境的目标是用于查看特定升级查询需要多长时间才能知道是否会出现任何停机(因为表在架构更改期间被锁定)

在第二个环境中执行 add 语句时

alter table Invoice add IsVerified bit not null default(0)
Run Code Online (Sandbox Code Playgroud)

查询立即退出,这很奇怪,因为里面有11M条记录。我预计至少会有一点延迟。即使是 select count(*) 也需要更长的时间。然而,在主生产数据库上,它需要更长的时间,超过 30 秒,因此我们必须将此查询计划到一个特殊的维护窗口中。执行查询时,没有任何东西阻止 SPID(使用 sp_who2 检查)

可能是什么原因,数据库的第二个副本似乎根本没有在 11M 记录数据库中添加列,而另一个主数据库无法及时完成(<30 秒)。也许一些特殊设置允许您添加默认值列而不需要写入所有记录?难道是因为我们的测试环境是Developer版而生产环境是Standard版?也许开发版中的某些特殊功能在 SQLStandard 中未激活?

select count(*) from Invoice //result: 11701200
SQL Server Execution Times:
   CPU time = 2375 ms,  elapsed time = 608 ms.
Run Code Online (Sandbox Code Playgroud)

要添加的脚本:

alter table Invoice add IsVerified bit not null default(0)
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 12 ms.
Run Code Online (Sandbox Code Playgroud)

Den*_*kin 5

添加 NOT NULL 列作为在线操作

从 SQL Server 2012 (11.x) Enterprise Edition开始,当默认值是运行时常量时,添加具有默认值的 NOT NULL 列是联机操作。这意味着无论表中有多少行,操作几乎都会立即完成。因为,表中的现有行在操作期间不会更新。相反,默认值仅存储在表的元数据中,并且根据需要在访问这些行的查询中查找该值。此行为是自动的。除了 ADD COLUMN 语法之外,不需要额外的语法来实现在线操作。运行时常量是一个表达式,它在运行时为表中的每一行生成相同的值,尽管它具有确定性。例如,常量表达式“我的临时数据”或系统函数GETUTCDATETIME()都是运行时常量。相反,函数 NEWID() 或 NEWSEQUENTIALID() 不是运行时常量,因为为表中的每一行生成唯一值。添加具有非运行时常量默认值的 NOT NULL 列始终会脱机运行,并且在操作期间会获取独占 (SCH-M) 锁。

在线架构更改仍然是 SQL Server 2019 (15.x) 的一项企业功能,因此您可以在开发人员版本上执行在线操作,而在标准版本上执行离线操作。

  • 鉴于目标是测试版本重要的架构升级性能,也许 @MichaelD 应该研究 [Visual Studio 订阅](https://visualstudio.microsoft.com/vs/pricing-details/),以便 SQL Server 标准版可用于开发和测试(非产品使用)。订阅还包括 Azure 积分。 (3认同)