索引维护

如果你关心你的索引(是的,这是索引的复数),你应该维护它们,特别是如果你经常插入或删除影响它们。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