Azure und insbesondere Azure SQL ist klasse – es nimmt einem viele Dinge der täglichen Verwaltung ab, einiges davon sogar automatisch. Klar, das hat seinen Preis, immerhin ist Azure SQL nicht ganz billig, aber wenn man es schon bezahlt, dann kann man auch seine Fähigkeiten nutzen. Eine davon ist, automatisch anhand der Nutzung einer Datenbank Empfehlungen für die Leistungsoptimierung zu geben. Diese kann man sich im UI bzw. dem Azure Portal anschauen. Dazu öffnet man entweder links im Blade den Punkt „Recommondations“ unterhalb von „Intelligent Performance“ oder den Punkt „Performance“ auf der Main-Page bei den Notifications:
Dort sieht man dann einige Empfehlungen aufgeführt (vorausgesetzt, Azure hat etwas gefunden, was wiederum eine regelmäßige Nutzung der Datenbank voraussetzt):
Diese Daten kann man sich auch automatisch abrufen und auf Wunsch dann z.B. an die Entwickler verteilen. Dazu bediene ich mich einfach der PowerShell:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | $ErrorActionPreference = "Stop" $SubscriptionId = "YOUR_SUBSCRIPTION_ID" function Get-SQLServerRecommendations() { # Define the resource types $resourceTypes = ("Microsoft.Sql/servers/databases") $advisors = ("CreateIndex", "DropIndex","DbParameterization","SchemaIssue"); $results = @() # Loop through all subscriptions $rgs = Get-AzureRmResourceGroup # Loop through all resource groups foreach($rg in $rgs) { $rgname = $rg.ResourceGroupName; # Loop through all resource types foreach($resourceType in $resourceTypes) { $resources = Get-AzureRmResource -ResourceGroupName $rgname -ResourceType $resourceType # Loop through all databases # Extract resource groups, servers and databases foreach ($resource in $resources) { $resourceId = $resource.ResourceId if ($resourceId -match ".*RESOURCEGROUPS/(?<content>.*)/PROVIDERS.*") { $ResourceGroupName = $matches['content'] } else { continue } if ($resourceId -match ".*SERVERS/(?<content>.*)/DATABASES.*") { $ServerName = $matches['content'] } else { continue } if ($resourceId -match ".*/DATABASES/(?<content>.*)") { $DatabaseName = $matches['content'] } else { continue } # Skip if master if ($DatabaseName -eq "master") { continue } # Loop through all Automatic tuning recommendation types foreach ($advisor in ($advisors -notmatch "SchemaIssue")) { $recs = Get-AzureRmSqlDatabaseRecommendedAction -ResourceGroupName $ResourceGroupName -ServerName $ServerName -DatabaseName $DatabaseName -AdvisorName $advisor foreach ($r in $recs) { if ($r.State.CurrentValue -eq "Active") { $object = New-Object -TypeName PSObject $object | Add-Member -Name 'SubscriptionId' -MemberType Noteproperty -Value $subscriptionId $object | Add-Member -Name 'ResourceGroupName' -MemberType Noteproperty -Value $r.ResourceGroupName $object | Add-Member -Name 'ServerName' -MemberType Noteproperty -Value $r.ServerName $object | Add-Member -Name 'DatabaseName' -MemberType Noteproperty -Value $r.DatabaseName $object | Add-Member -Name 'Advisor' -MemberType Noteproperty -Value $advisor $object | Add-Member -Name 'Script' -MemberType Noteproperty -Value $r.ImplementationDetails.Script $results += $object } } } } } } Return $results } $AzurePasswordSecure = ConvertTo-SecureString "$($YOUR_AZURE_PASSWORD)" -AsPlainText -Force $AzureCredentials = New-Object System.Management.Automation.PSCredential ("$YOUR_AZURE_USER", $AzurePasswordSecure) Connect-AzureRmAccount -Credential $AzureCredentials | Out-Null Select-AzureRmSubscription -Subscription $SubscriptionId | Out-Null $Recommendations = Get-SQLServerRecommendations $table = $Recommendations | Sort-Object DatabaseName,Advisor | Format-Table Databasename,Advisor,Script -AutoSize -Wrap Write-Output $table $head = "<style> td {background-color:lightgrey;} table {width:100%;} th {font-size:14pt;background-color:lightblue;} </style> <title>SQL Server performance recommendations</title>" [string]$html = $Recommendations | ConvertTo-Html -Property Databasename,Advisor,Script -Body "<h1>Azure SQL Server automatic tuning recommendations for $stage</h1>Auto-generated by PUT_SOMETHING_HERE<br><br>" -Head $head Send-MailMessage -Body $html -SmtpServer YOUR.SMTPSERVER.COM -From sender@domain.com -To recipient@domain.com -Subject "MS SQL Recommendations - $(Get-Date -Format "yyyy-dd-MM HH:mm:ss")" -BodyAsHtml |
Dieses Script wiederum kann man dann z.B. per Jenkins regelmäßig auslösen. Oder alternativ ein Azure Automation Runbook dafür anlegen… Viel Spaß beim Ausprobieren!
Die Mails sehen dann in etwa so aus: