添加列時環境之間的性能差異
我們有 2 個完全相同的數據庫環境。第二個環境包含生產數據庫的副本,並在 Invoice 表中託管大約 11M 條記錄。此環境的目標用於查看特定升級查詢需要多長時間才能知道是否會有任何停機時間(因為表在架構更改期間被鎖定)
在第二個環境中執行 add 語句時
alter table Invoice add IsVerified bit not null default(0)
查詢立即退出,這很奇怪,因為其中有 11M 條記錄。我預計至少會有一點延遲。即使是選擇計數(*)也需要更長的時間。然而,在主生產數據庫上,它需要更長的時間,超過 30 秒,因此我們必須將此查詢計劃到一個特殊的維護視窗中。在執行查詢時,沒有任何東西阻塞 SPID(使用 sp_who2 檢查)
可能是什麼原因,數據庫的第二個副本似乎根本沒有努力在 11M 記錄數據庫中添加一列,而另一個 maindb 無法及時完成(<30 秒)。也許有一些特殊的設置可以讓你添加一個預設值列而不需要寫入所有記錄?難道是因為我們的測試環境是開發版,而生產環境是標準版?也許開發版中的某些特殊功能在 SQLStandard 中不可用?
select count(*) from Invoice //result: 11701200 SQL Server Execution Times: CPU time = 2375 ms, elapsed time = 608 ms.
要添加的腳本:
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.
從 SQL Server 2012 (11.x)企業版開始,當預設值為執行時常量時,添加具有預設值的 NOT NULL 列是聯機操作。這意味著儘管表中有多少行,但操作幾乎是瞬間完成的。因為,表中的現有行在操作期間不會更新。相反,預設值僅儲存在表的元數據中,並根據需要在訪問這些行的查詢中查找該值。這種行為是自動的。除了 ADD COLUMN 語法之外,不需要額外的語法來實現線上操作。執行時常量是一個表達式,它在執行時為表中的每一行生成相同的值,儘管它具有確定性。例如,常量表達式“我的臨時數據”或系統函式 GETUTCDATETIME() 是執行時常量。相比之下,函式 NEWID() 或 NEWSEQUENTIALID() 不是執行時常量,因為為表中的每一行生成一個唯一值。添加具有非執行時常量的預設值的 NOT NULL 列始終離線執行,並且在操作期間獲取獨占 (SCH-M) 鎖。
線上架構更改仍然是 SQL Server 2019 (15.x) 的一項企業功能,因此您可以在開發人員版上執行線上操作,而在標準版上則離線執行。