索引維護

如果你關心你的索引(是的,這是索引的複數),你應該維護它們,特別是如果你經常插入或刪除影響它們。Azure 自動化提供了一個幾乎就緒的 Runbook,你可以使用它並安排執行自動索引重建。以下是你需要做的事情:首先,匯入 Runbook:

匯入 Runbook 後,你必須進入編輯模式並按 Runbook 上的釋出,它才會變為活動狀態。在編輯模式下,你還可以檢視 Runbook 的原始碼。

然後你必須為 Runbook 新增一個憑證,可以用來連線資料庫(基本上它只是一個鍵值對,其中值是使用者名稱和密碼,金鑰可以從指令碼中使用參考這個特定的憑證)。這必須是可以對資料庫進行身份驗證的使用者密碼對,並且使用者應該有權訪問資料庫狀態並執行 ALTER INDEX 語句: 最後使用指定的引數計劃 Runbook。你還可以測試 Runbook 並立即啟動它(但在這種情況下你還必須指定引數):

現在不幸的是,我發現這個預設的 Runbook 存在兩個問題。

首先,它只處理預設架構中的表。這並不總是足夠的,所以繼續找到這條線:

SELECT  t.name AS TableName, t.OBJECT_ID FROM sys.tables t

並改為:

SELECT  '['+SCHEMA_NAME(t.schema_id)+'].['+t.name+']' AS TableName, t.OBJECT_ID FROM sys.tables t

此外,指令碼無法在連線字串中的任何位置處理特殊字元(例如“,”或=)。要處理這些字元,你可以使用正確的連線字串轉義,或者更好的是,使用 connectionstring 構建器。無論你看到連線字串在指令碼中建立(應該有兩個地方),將其更改為使用 connectionstring builder:

$connStringBuilder = New-Object System.Data.SqlClient.SqlConnectionStringBuilder
$connStringBuilder["Server"] = "tcp:$using:SqlServer,$using:SqlServerPort"
$connStringBuilder["Database" ] = "$using:Database"
$connStringBuilder["User ID"] = "$using:SqlUsername"
$connStringBuilder["Password"] = "$using:SqlPass"
$connStringBuilder["Trusted_Connection"] = $False
$connStringBuilder["Encrypt"] = $True
$connStringBuilder["Connection Timeout"] = "30"
$connString = $connStringBuilder.ConnectionString                
$Conn = New-Object System.Data.SqlClient.SqlConnection($connString)

你還可以更改實際計算碎片的查詢。這是查詢:

SELECT a.object_id, avg_fragmentation_in_percent
    FROM sys.dm_db_index_physical_stats (
           DB_ID(N'$Database')
         , OBJECT_ID(0)
         , NULL
         , NULL
         , NULL) AS a
    JOIN sys.indexes AS b 
    ON a.object_id = b.object_id AND a.index_id = b.index_id;

如果將 sys.dm_db_index_physical_stats 的最後一個引數從 NULL 更改為 DETAILED,則可以更好地估計索引的碎片程度。

我已經將此版本上傳到 Github: https//github.com/conwid/IndexRebuildScript