Sql-Server

了解 SQL Server 快照還原的最低性能

  • July 6, 2021

我目前正在研究我公司的測試套件中快照恢復的性能。我在網上閱讀了很多關於執行還原所需時間與快照大小成正比的材料——即已復製到快照稀疏文件的頁數。我大部分發現這是真的,這是一個直覺的結論。但是,當快照足夠小時,您似乎會遇到“最低”性能。我沒有在任何地方看到這個討論,我不太明白。

本質上,我發現快照的大小與恢復快照所用的時間沒有線性關係。相反,隨著快照大小接近零,恢復時間接近 3.5 秒。我相信這層樓會根據您的設置有所不同,但是在我的本地開發機器和我們研究過的數十個建構伺服器上,我們都無法將快照的還原時間減少到大約三個以下半秒。

我花了最後一天進行本地測試來幫助說明這種現象。我通過創建一個包含單個表和單個整數值列的新數據庫來執行測試。我在數據庫為空時創建了一個快照,然後填充表並恢復了快照,使用 SSMS 客戶端統計資訊來衡量恢復操作花費了多長時間。當呼叫 restore 時,我將恢復時間(以毫秒為單位)與表中的行數繪製成圖表:

按快照中的行恢復時間

值得注意的是,當沒有任何東西可以恢復時,恢復時間是一個相對恆定的 0.15-.3s。這裡是 X 軸上的 0。但只要我們只有一行要恢復,時間就會上升到 3 秒多一點。我有其他數據在我們的建構伺服器上顯示了這種現象——它不是我的機器本地的,所以它一定與快照恢復的實現有關。但是我在網上找不到任何解釋這種現象的東西。誰能幫我理解一下?這是只影響我的事情嗎?是否可以將快照還原的性能提高到超過此限制?任何幫助表示讚賞 - 謝謝!

在嘗試了Hannah Vernon 給出的範例之後,我相信我已經找到了快照還原問題的根源。

為了在我的機器上重現這個問題,在我們的測試套件中,我們在快照還原之前將還原目標數據庫設置為單個使用者,並使用類似alter database x set single_user with rollback immediate. 之後我們將其設置回多使用者。據我所知,這就是發言時間的來源。在我的機器上單獨執行這兩個 alter database 語句大約需要 3 秒- 這解釋了大約 3.5 秒的恢復操作。約 3 秒回滾打開的連接,約 0.5 秒進行恢復。這也與我們的“空”恢復時間有關。

對我來說,“空”恢復花費如此短的時間仍然有點神秘,即使在設置單/多使用者語句的情況下,就像我們的其他恢復一樣。我的猜測是,在我的測試和我們的測試套件中,這可能在特殊條件下發生,可能是當沒有其他使用者連接到數據庫時。我今天似乎無法在我的機器上重現 0.15-3 秒的時間來確認這些條件,但我仍然在我們的建構機器上看到它。無論如何,這與 99% 的快照恢復案例都不是特別相關,至少不是我的,所以我放棄了這裡的調查。這是我方法中的主要紅鯡魚。

非常感謝 Hannah 嘗試重現該問題並在此問題上與我反复討論!我將把我的文章標記為這個問題的答案,因為如果其他人遇到類似問題,它是對我問題的更完整的答案,但所有功勞歸於 Hannah。

我正在嘗試重現您的場景,並且看到快照還原時間在 600 到 800 毫秒之間。

這是複製品:

USE master;
IF DB_ID('test_snapshot') IS NOT NULL
BEGIN
   ALTER DATABASE test_snapshot SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
   DROP DATABASE test_snapshot;
END
GO
CREATE DATABASE test_snapshot
ON     (NAME = 'test_snapshot_data', FILENAME = '/data/mssql/data/test_snapshot_data.mdf')
LOG ON (NAME = 'test_snapshot_log' , FILENAME = '/data/mssql/logs/test_snapshot_log.ldf');
GO

USE test_snapshot;
GO
CREATE TABLE dbo.TestTable (id int NOT NULL);
GO
USE master;
GO

SET STATISTICS TIME OFF;
DECLARE @msg nvarchar(1000);
SET @msg = 'Create Snapshot';
RAISERROR (@msg, 0, 0) WITH NOWAIT;
SET STATISTICS TIME ON;
CREATE DATABASE test_snapshot_snap 
ON 
    (NAME = test_snapshot_data   , FILENAME = '/data/mssql/data/test_snapshot_data.ss')
AS SNAPSHOT OF test_snapshot;
SET STATISTICS TIME OFF;
GO

USE test_snapshot;
GO
INSERT INTO dbo.TestTable (id) VALUES (0);
GO
USE master;
GO

DECLARE @msg nvarchar(1000);
SET @msg = 'Restore Snapshot';
RAISERROR (@msg, 0, 0) WITH NOWAIT;
SET STATISTICS TIME ON;
RESTORE DATABASE [test_snapshot] FROM DATABASE_SNAPSHOT = 'test_snapshot_snap';
SET STATISTICS TIME OFF;

SET @msg = 'Drop Snapshot';
RAISERROR (@msg, 0, 0) WITH NOWAIT;
SET STATISTICS TIME ON;
DROP DATABASE test_snapshot_snap;
SET STATISTICS TIME OFF;

有幾點需要注意,這是在我的 HyperV VM 筆記型電腦上的 SQL Server 15.0.4102.2(RedHat Enterprise Linux 上的 SQL Server 2019)上執行的。VM 託管在速度非常快的 NVMe SSD 上。

統計時間結果始終類似於:

創建快照

SQL Server 執行時間:
CPU 時間 = 37 毫秒,經過時間 = 118 毫秒。

(受影響的 1 行)
恢復快照

SQL Server 執行時間:
CPU 時間 = 193 毫秒,經過時間 = 605 毫秒。
刪除快照

SQL Server 執行時間:
CPU 時間 = 12 毫秒,經過時間 = 25 毫秒。

完成時間:2021-07-06T12:44:46.0651782-05:00

如果我註釋掉CREATE TABLEandINSERT INTO語句,我發現執行時間沒有統計上的顯著差異。

引用自:https://dba.stackexchange.com/questions/295133