<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Performance &#8211; Haikos Blog</title>
	<atom:link href="https://www.hertes.net/tag/performance/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.hertes.net</link>
	<description>Blog von Haiko Hertes zu allen Themen rund um Microsoft, Cloud und Datacenter</description>
	<lastBuildDate>Thu, 28 Mar 2019 09:46:54 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Azure / PowerShell – Azure SQL Performance Empfehlungen per PowerShell abholen und verteilen</title>
		<link>https://www.hertes.net/2019/03/azure-powershell-azure-sql-performance-empfehlungen-per-powershell-abholen-und-verteilen/</link>
					<comments>https://www.hertes.net/2019/03/azure-powershell-azure-sql-performance-empfehlungen-per-powershell-abholen-und-verteilen/#respond</comments>
		
		<dc:creator><![CDATA[Haiko]]></dc:creator>
		<pubDate>Wed, 27 Mar 2019 18:10:15 +0000</pubDate>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Automatisierung]]></category>
		<category><![CDATA[Azure SQL]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Tuning]]></category>
		<guid isPermaLink="false">https://www.hertes.net/?p=3755</guid>

					<description><![CDATA[Azure und insbesondere Azure SQL ist klasse &#8211; 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 &#8222;Recommondations&#8220; unterhalb von &#8222;Intelligent Performance&#8220; oder den Punkt &#8222;Performance&#8220; auf der Main-Page bei den Notifications: Dort sieht man dann&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Azure und insbesondere Azure SQL ist klasse &#8211; 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 &#8222;Recommondations&#8220; unterhalb von &#8222;Intelligent Performance&#8220; oder den Punkt &#8222;Performance&#8220; auf der Main-Page bei den Notifications:</p>



<figure class="wp-block-image"><img fetchpriority="high" decoding="async" width="1024" height="501" src="https://www.hertes.net/wp-content/uploads/2019/03/image-1024x501.png" alt="" class="wp-image-3756" srcset="https://www.hertes.net/wp-content/uploads/2019/03/image-1024x501.png 1024w, https://www.hertes.net/wp-content/uploads/2019/03/image-300x147.png 300w, https://www.hertes.net/wp-content/uploads/2019/03/image-768x375.png 768w, https://www.hertes.net/wp-content/uploads/2019/03/image.png 1921w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Dort sieht man dann einige Empfehlungen aufgeführt (vorausgesetzt, Azure hat etwas gefunden, was wiederum eine regelmäßige Nutzung der Datenbank voraussetzt):</p>



<figure class="wp-block-image"><img decoding="async" width="1024" height="482" src="https://www.hertes.net/wp-content/uploads/2019/03/image-2-1024x482.png" alt="" class="wp-image-3758" srcset="https://www.hertes.net/wp-content/uploads/2019/03/image-2-1024x482.png 1024w, https://www.hertes.net/wp-content/uploads/2019/03/image-2-300x141.png 300w, https://www.hertes.net/wp-content/uploads/2019/03/image-2-768x361.png 768w, https://www.hertes.net/wp-content/uploads/2019/03/image-2.png 1721w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>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:</p>



<pre lang="PowerShell" line="1">
$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
</pre>



<p></p>



<p>Dieses Script wiederum kann man dann z.B. per Jenkins regelmäßig auslösen. Oder alternativ ein Azure Automation Runbook dafür anlegen&#8230; Viel Spaß beim Ausprobieren!</p>



<p>Die Mails sehen dann in etwa so aus:</p>



<figure class="wp-block-image"><img decoding="async" width="802" height="896" src="https://www.hertes.net/wp-content/uploads/2019/03/image-3.png" alt="" class="wp-image-3760" srcset="https://www.hertes.net/wp-content/uploads/2019/03/image-3.png 802w, https://www.hertes.net/wp-content/uploads/2019/03/image-3-269x300.png 269w, https://www.hertes.net/wp-content/uploads/2019/03/image-3-768x858.png 768w" sizes="(max-width: 802px) 100vw, 802px" /></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://www.hertes.net/2019/03/azure-powershell-azure-sql-performance-empfehlungen-per-powershell-abholen-und-verteilen/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
