Aracılığıyla paylaş


G/Ç Performans Analizi (Önizleme) - Azure VM'lerinde SQL Server

Şunlar için geçerlidir: Azure VM'de SQL Server

Bu makalede, sanal makinelerin ve veri disklerinin sınırlarının aşılmasından kaynaklanan sorunları bulmak için Azure Sanal Makineler'de (VM) SQL Server'ın G/Ç performansını analiz etme öğretilmiştir.

Not

Azure portalındaki Azure VM'lerinde SQL Server için G/Ç Analizi şu anda önizleme aşamasındadır.

Genel bakış

Çeşitli araçlar SQL Server performans sorunlarını gidermenize yardımcı olsa da, bunu Azure VM'sinde etkili bir şekilde yapmak için hem konak düzeyinde hem de SQL Server örneğinizde neler olduğunu anlamanız önemlidir; burada genellikle konak ölçümlerini SQL Server iş yükleriyle ilişkilendirmek zor olabilir. Azure VM'lerinde SQL Server, sanal makine ve veri diskleri sınırlarının aşılmasından kaynaklanan IOPS (Saniyede Giriş/Çıkış) ve aktarım hızı azaltmasından kaynaklanan performans sorunlarını tanımlamayı kolaylaştırır.

Sorunu gösteren performans ölçümleri ve bu sorunu gidermeye yönelik olası adımlar Azure portalında kullanılabilir ve Azure CLI ile sorgulanabilir.

Azure portalındaki SQL sanal makineleri kaynağınızın Depolama bölmesi size yardımcı olur:

Ölçümleri anlama

G/Ç Analizi sekmesi, disk gecikme süresini ve VM veya disk G/Ç azaltmasını belirlemek için Azure Ölçümleri'ne dayanır. Azure Ölçümleri 30 saniyede bir örneklenir ve bir dakikaya toplanır.

Sistem azaltma ve disk gecikme süresini izler. Bazı azaltmalar beklenir ve disk gecikme süresi olmadığı sürece yoksayılır. Arka arkaya 5 dakikalık bir süre içinde 500 milisaniyeden fazla disk gecikmesi gözlemleniyorsa sistem:

  • Performans ölçümlerini daha ayrıntılı bir şekilde inceler
  • Kısıtlanan kaynağı tanımlar
  • Olası kök nedenler ve azaltma adımları sağlar

Aşağıdaki tabloda sorunlu azaltma sorunlarını tanımlamak için kullanılan Azure Ölçümleri açıklanmaktadır:

Azure Ölçümü Ölçüm açıklaması Sorunlu durum G/Ç azaltma sonuçları
Disk gecikme süresi (önizleme) İzlenen süre boyunca veri diski için G/Ç'leri tamamlamak için ortalama süre. Değerler milisaniye cinsindendir. > Art arda 5 dakika içinde 500 milisaniye Sistemin olası azaltmayı daha fazla araştırması için bir gecikme sorunu vardır.
VM Tarafından Tüketilen Önbelleğe Alınmış IOPS Yüzdesi Maksimum önbelleğe alınmış sanal makine IOPS sınırı üzerinden tamamlanan toplam IOPS ile hesaplanan yüzde. >= 5 dakikalık art arda %95 VM azaltması var. SQL sanal makinesinde çalışan uygulama, sanal makinede kullanılabilen en yüksek önbelleğe alınmış IOPS kapasitesini tam olarak kullanıyor. Uygulamanın depolama talepleri, sanal makinenin temel depolama yapılandırması tarafından sağlanan önbelleğe alınmış IOPS'yi aşıyor.
VM Önbelleğe Alınan Bant Genişliği Tüketilen Yüzdesi Maksimum önbelleğe alınmış sanal makine aktarım hızı üzerinden tamamlanan toplam disk aktarım hızıyla hesaplanan yüzde. >= 5 dakikalık art arda %95 VM azaltması var. SQL sanal makinesinde çalışan uygulama, veri aktarımı için kullanılabilir en yüksek önbelleğe alınmış disk bant genişliğini kullanıyor. Uygulamanın veri aktarımı talepleri, sanal makinenin temel depolama yapılandırması tarafından sağlanan önbelleğe alınmış bant genişliği kaynaklarını aşıyor. 
VM Tarafından Tüketilen Önbelleğe Alınmamış IOPS Yüzdesi Bir sanal makinedeki toplam IOPS tarafından hesaplanan yüzde, en fazla kazınmamış sanal makine IOPS sınırı üzerinden tamamlanır. >= 5 dakikalık art arda %95 VM azaltması var. SQL sanal makinesinde çalışan uygulama, sanal makinede kullanılabilen izin verilen en yüksek çıkarılmamış IOPS kapasitesini kullanıyor. Uygulamanın depolama talepleri, sanal makinenin temel depolama yapılandırması tarafından sağlanan kazınmamış IOPS kaynaklarını aşıyor.
VM Tarafından Tüketilen Önbelleğe Alınmamış Bant Genişliği Yüzdesi Sağlanan maksimum sanal makine aktarım hızı üzerinden tamamlanan bir sanal makinedeki toplam disk aktarım hızıyla hesaplanan yüzde. >= 5 dakikalık art arda %95 VM azaltması var. SQL sanal makinesinde çalışan uygulama, veri aktarımı için izin verilen en yüksek çıkarılmamış disk bant genişliğini kullanıyor. Uygulamanın veri aktarımı talepleri, sanal makinenin temel depolama yapılandırması tarafından sağlanan çıkarılmamış bant genişliği kaynaklarını aşıyor.
Tüketilen Veri Diski IOPS Yüzdesi Sağlanan veri diski IOPS üzerinden tamamlanan veri diski IOPS tarafından hesaplanan yüzde. >= 5 dakikalık art arda %95 Veri diski azaltması var. SQL sanal makinesinde çalışan uygulama, sağlanan veri diski için IOPS sınırına ulaştı. Uygulamanın depolama talepleri, seçilen disk yapılandırmasının performans özelliklerini aşıyor.
Tüketilen Veri Diski Bant Genişliği Yüzdesi Sağlanan veri diski aktarım hızı üzerinden tamamlanan veri diski aktarım hızı tarafından hesaplanan yüzde. >= 5 dakikalık art arda %95 Veri diski azaltması var. SQL sanal makinesinde çalışan uygulama, sağlanan veri diski için IOPS sınırına ulaştı. Uygulamanın depolama talepleri, seçilen disk yapılandırmasının performans özelliklerini aşıyor.

G/Ç analizi bulguları

G/Ç analizi, son 24 saat içindeki performans ölçümleri analizine göre şunların olduğunu belirler:

  • Azaltma yok
  • VM düzeyi G/Ç azaltma
  • Disk düzeyinde G/Ç azaltma

G/Ç azaltma sorunu yok

Performans sorunu yaşıyorsanız ancak disk gecikmesi yoksa performans sorunu G/Ç azaltma sorunundan kaynaklanmamaktadır. Diğer alanları araştırmanız gerekir. Sisteminizin verimli bir şekilde yapılandırıldığından emin olmak veya SQL Server performansı sorunlarını gidermek için yararlı bağlantılar bulmak için Azure VM'lerinde SQL Server için en iyi yöntemler denetim listesini kullanabilirsiniz. SQL en iyi yöntemler değerlendirme özelliğini etkinleştirirseniz, SQL Server VM'niz için önerilerin tam listesini görebilirsiniz.

VM düzeyi G/Ç azaltma sorunu

Azure Sanal Makineler, her birinin farklı özelliklere ve performans özelliklerine sahip çeşitli iş yükleri için farklı seri ve boyutlarda gelen bulut tabanlı bilgi işlem kaynaklarıdır. SQL Server iş yükleri için genellikle SQL Server iş yükleri için önerilen seriler Ebdsv5, M ve Mv2 serisi gibi bellek için iyileştirilmiş serilerdir.

VM'nin boyutu, SQL Server örneği için kullanılabilir vCPU' ların, belleğin ve depolama alanının sayısını belirler. Depolama ile karşılaştırıldığında, müşterilerin sanal makinelerini yeniden boyutlandırması ve uygulama kaynağı gereksinimlerine göre vm'lerinin ölçeğini artırması ve azaltması nispeten kolaydır. IOPS ve aktarım hızının VM düzeyinde kısıtlanması mümkün olduğundan, performans gereksinimlerine ve iş yükünün maliyetine göre uygun bir VM boyutu seçin.

Azure'a geçiş gerçekleştiriyorsanız, geçerli SQL Server yapılandırmanızı ve kullanımınızı analiz etmek ve Azure'daki iş yükünüz için en iyi VM boyutunu önermek için Data Migration Yardımcısı ve SKU Önerileri gibi araçları kullanabilirsiniz.

Aşağıdaki Azure ölçümleri, iş yükünün VM tarafından uygulanan sınırları aşmaktan kısıtlanmış olduğunu belirlemek için kullanılır:

  • VM Tarafından Tüketilen Önbelleğe Alınmış IOPS Yüzdesi
  • VM Tarafından Tüketilen Önbelleğe Alınmış Bant Genişliği Yüzdesi
  • VM Tarafından Tüketilen Önbelleğe Alınmamış IOPS Yüzdesi
  • VM Tarafından Tüketilen Önbelleğe Alınmamış Bant Genişliği Yüzdesi

VM azaltma hakkında aşağıdaki önemli noktaları göz önünde bulundurun:

  • Sanal makinenizi bir VM serisi içinde yeniden boyutlandırarak belleği, sanal çekirdekleri, aktarım hızını ve IOPS'yi artırabilirsiniz.
  • VM boyutunu, veri disklerinin sayısının hedef VM boyutu için maksimum veri diski sınırını aştığı bir düzeye indiremezsiniz.
  • Azaltma düzenini belirlemek önemlidir. Örneğin, azaltmada sık görülen ani artışlar büyük olasılıkla iş yükünün ayarlanmasıyla çözülebilirken, sürekli ani artışlar temel alınan depolamanın iş yükünü işleyemediğini gösterebilir.

Disk düzeyi G/Ç azaltma sorunu

SQL sanal makine müşterileri için, depolamayı değiştirmek bir sanal makineyi yeniden boyutlandırmaktan daha zor olduğundan, en iyi performans için uygun şekilde yapılandırmanın en kritik yönü depolamadır. Örneğin, Premium SSD diskleri için IOPS veya aktarım hızını artırmak için herhangi bir değişiklik yapmak için yeni bir depolama havuzu oluşturulması gerekir. Bu nedenle, dağıtımdan sonra performans sorunlarını önlemek için planlama aşamasında depolama yapılandırmasını hem fiyat hem de performans açısından iyileştirmek çok önemlidir.

Aşağıdaki Azure ölçümleri, iş yükünün disk tarafından uygulanan sınırların aşılmasından kısıtlanmış olduğunu belirlemek için kullanılır:

  • Tüketilen Veri Diski IOPS Yüzdesi

  • Veri Diski Bant Genişliği Tüketilen Yüzdesi Disk düzeyi G/Ç azaltma hakkında aşağıdaki önemli noktaları göz önünde bulundurun:

  • Veri diski SQL Server performansı için kritik öneme sahiptir. SQL Server verilerinin (.mdf) ve günlük (.df) dosyalarının veri diskinde yerleştirilmesi önerilir.

  • Veri diski düzeyinde azaltma için, varsa okuma önbelleğini etkinleştirin.

Tüketilen Veri Diski IOPS Yüzdesi

Veri Diski IOPS Tüketilen Yüzdesi ölçümü, IOPS tüketimini disk düzeyinde ölçer. Genel olarak, yüksek IOPS gereksinimleri yüksek işlemsel, OLTP tabanlı uygulamalar ve iş yükleriyle ilişkilendirilir.   Aşağıdaki senaryolar veya koşullar potansiyel olarak veri diski IOPS sınırlarını aşabilir:

  • Yüksek İşlem İş Yükü (IOPS):Uygulama sık sık okuma ve yazma işlemleri içeren yüksek hacimli veritabanı işlemlerini işliyorsa, ayrılan IOPS'yi hızla kullanabilir. 
  • Verimsiz Sorgular: Kötü iyileştirilmiş SQL sorguları veya veri alma işlemleri aşırı G/Ç etkinliğine yol açarak beklenenden daha fazla IOPS tüketebilir. 
  • Eşzamanlı Kullanıcılar: Birden çok kullanıcı veya oturum aynı anda veritabanına erişiyorsa ve G/Ç istekleri oluşturuyorsa, kümülatif etki IOPS sınırına ulaşılmasıyla sonuçlanabilir. 
  • Kaynakları Birleştirme: Temel alınan fiziksel altyapı diğer kiracılarla veya iş yükleriyle yoğun bir şekilde paylaşılıyorsa, sanal makineniz için kullanılabilir IOPS'yi etkileyebilir. 
  • Geçici Ani Artışlar: Toplu işlem veya veri geçişleri gibi iş yükündeki geçici ani artışlar, ayrılan IOPS'yi aşan G/Ç talebinde ani artışlara neden olabilir. 
  • Küçük disk boyutu: Sağlanan veri diski boyutu görece küçükse, IOPS kapasitesi sınırlı olabilir. Tek tek küçük disklerin IOPS sınırları düşüktür ve uygulamanın talepleri bu sınırı aşarsa "Veri Diski IOPS Tüketilen Yüzdesi" %100'e ulaşır. 
  • Yetersiz disk türü: G/Ç yoğunluklu bir uygulama için düşük performanslı bir disk türü (Standart HDD gibi) seçmek IOPS sınırlamalarına yol açabilir. 
  • İyileştirilmemiş disk şeridi boyutu: Depolama yapılandırması iş yükü için iyileştirilmemişse, en iyi duruma getirilmemiş IOPS performansına yol açabilir. 

Veri diski IOPS sınırını aşmamak için aşağıdaki adımları göz önünde bulundurun:

  • Gereksiz G/Ç işlemlerini en aza indirmek için SQL sorgularını ve veritabanı tasarımını iyileştirin. 
  • Uygulamanızın IOPS gereksinimlerine uyan uygun bir disk türü (Standart SSD veya Premium SSD) seçin. 
  • Kullanılabilir IOPS kapasitesini artırmak için daha büyük disk boyutları kullanın. 
  • RAID yapılandırmalarını kullanarak G/Ç'i birden çok veri diski arasında dağıtın. 

Veri Diski Bant Genişliği Tüketilen Yüzdesi

Veri Diski Bant Genişliği Tüketilen Yüzdesi Azure ölçümü, bant genişliği kullanımını disk düzeyinde ölçer. Genellikle yüksek aktarım hızı gereksinimleri veri ambarı, veri reyonu, raporlama, ETL ve diğer veri analizi iş yükleriyle ilişkilendirilir.

Aşağıdaki senaryolar veya koşullar potansiyel olarak veri diski bant genişliği sınırlarını aşabilir:

  • Büyük veri aktarımları: Disk ve SQL veritabanı arasında sık, büyük ölçekli uygulama veri aktarımları, kullanılabilir veri diski bant genişliğini hızla tüketebilir. 
  • Toplu veri yükleme: Toplu veri ekleme, güncelleştirme veya içeri aktarma işlemleriyle ilişkili disk aktarım etkinlikleri yüksek bant genişliği tüketimine yol açabilir. 
  • Veri ambarı veya analiz: Ağır veri ambarı, analiz işleme veya raporlama içeren uygulamalar, bant genişliği sınırlarının aşılması olasılığına neden olabilecek önemli veri taşıma işlemleri oluşturabilir.
  • Yüksek veri yedekliliği teknolojisi / çoğaltma: İlişkili veri kopyalama, disk tabanlı çoğaltma, veri yansıtma veya diğer yedeklilik mekanizmalarını kullanır, bant genişliği doygunluğuna katkıda bulunabilir. 
  • Veri yedekleme ve geri yükleme: Sık veri yedeklemeleri, anlık görüntüler veya geri yükleme işlemleri önemli veri diski bant genişliğini tüketebilir. 
  • Paralel sorgu yürütme: Büyük veri taramaları veya birleştirmeler içeren paralel sorgular, bant genişliği kullanımına neden olan önemli veri hareketlerine yol açabilir. 
  • Yükseltilmiş ağ trafiği: Sanal makine ile diğer kaynaklar arasındaki veri aktarımları gibi yüksek ağ etkinliği, veri diski bant genişliği kullanılabilirliğini dolaylı olarak etkileyebilir. 
  • Yetersiz disk türü: Yüksek veri aktarımı gereksinimlerine sahip bir uygulama için düşük performanslı bir disk türü seçmek bant genişliği sınırının aşılmasıyla sonuçlanabilir. 
  • Eşzamanlı veri yoğunluklu işlemler: Aynı diskteki verilere erişen ve veri aktaran birden çok eşzamanlı işlemin veya oturumun birleştirilmiş etkisi bant genişliği sınırına ulaşılmasıyla sonuçlanabilir. 
  • İyileştirilmemiş sorgular veya ETL işlemleri: Kötü iyileştirilmiş SQL sorguları veya Ayıklama, Dönüştürme, Yükleme (ETL) işlemleri aşırı bant genişliği tüketimine neden olan aşırı veri hareketine yol açabilir. 

Veri diski bant genişliği sınırını aşmamak için aşağıdaki adımları göz önünde bulundurun:

  • Gereksiz veri taşımayı en aza indirmek için veri aktarımı işlemlerini iyileştirin. 
  • Premium SSD veya Premium SSD v2 gibi daha yüksek bant genişliği kapasitesi sunan daha yüksek performanslı disk türlerini kullanmayı göz önünde bulundurun.
  • Bölümleme veya parçalama gibi teknikleri kullanarak verileri birden çok disk arasında dağıtma.
  • Veri hareketini azaltmak için sorguları ve veri işlemeyi iyileştirin ve paralelleştirin.
  • Aktarılan veri hacmini azaltmak için sıkıştırma ve verimli veri depolama mekanizmaları kullanın.
  • Performans ölçümlerini izleyin ve gerektiğinde depolama yapılandırmalarınızın ölçeğini büyütün. Premium SSD v2, müşterilerin IOPS ve aktarım hızını isteğe bağlı olarak ölçeklendirmesine olanak tanır.
  • IOPS sınırlamalarının nedenini belirlemek ve SQL sanal makinenizin depolama performansını iyileştirmek için uygun eylemleri yapmak için performans ölçümlerini düzenli olarak izlemek ve analiz etmek önemlidir.

İpucu

Performans ölçümlerini düzenli olarak izlemek, veri aktarımı işlemlerini ayarlamak ve disk yapılandırmalarını iyileştirmek, SQL sanal makineniz için veri diskinizin performansının sınırları aşmadan en iyi durumda kalmasını sağlar.

Kötü yapılandırılmış depolama sistemleri performans sorunlarına yol açabileceğinden, Azure vm'lerinde SQL Server'ınız ile ilgili depolama yapılandırma sorunlarını belirlemek üzere SQL en iyi yöntemler değerlendirme kurallarının diske özgü bir alt kümesini çalıştırmak için Azure portalındaki Depolama bölmesini kullanabilirsiniz. SQL en iyi yöntemler özelliği, SQL Değerlendirme API'sini temel alır.

Önerilerin tam listesini GitHub'da görüntüleyebilirsiniz. GitHub'daki kurallardaki kimlik sütununu filtreleyerek, Azure portalındaki SQL sanal makineleri kaynağınız için Depolama bölmesinin G/Ç yapılandırması en iyi yöntemleri sekmesinde doğrulanan SQL VM disk yapılandırma kurallarını görebilirsiniz.

  • AzSqlVmSize
  • AzDataDiskCache
  • AzDataDiskStriping
  • AzDataOnDataDisks
  • AzDbDefaultLocation
  • AzDiskColumnCount
  • AzErrorLogLocation
  • AzPremSsdDataFiles
  • AzTempDbFileLocation
  • AzTranLogDiskCache
  • NtfsBlockSizeNotFormatted
  • LockedPagesInMemory

G/Ç ile ilgili en iyi yöntemler sekmesinde Değerlendirmeyi çalıştır'ı kullanarak yapılandırmanızın bir değerlendirmesini başlatın. Bu değerlendirmenin tamamlanması birkaç dakika sürer (çok sayıda veritabanı ve nesne yoksa). Alternatif olarak, en son kullanılabilir sonuçlar için bir zaman damgası görürseniz, Önceki değerlendirmelerdeki bulguları gözden geçirmek için En son sonuçları getir'i kullanabilirsiniz.

PowerShell ile G/Ç'leri analiz etme

SQL Server VM'nizin G/Ç performansını analiz etmek için G/Ç Analizi PowerShell betiğini de kullanabilirsiniz:

# Enter parameters
$subscriptionId = Read-Host "<Subscription ID>"
$resourceGroup = Read-Host "<Resource Group>"
$vmName = Read-Host "<Virtual machine name>"

# Set resource details
$resourceType = "Microsoft.Compute/virtualMachines"
$resourceId = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup/providers/$resourceType/$vmName"

# Get Azure access token
$accessToken = az account get-access-token --query accessToken -o tsv

# Invoke Azure Monitor Metrics API
function Get-Metrics {
    [CmdletBinding()]
    param (
        [string]$accessToken,
        [string]$resourceId,
        [string]$metricNames,
        [string]$apiVersion = "2023-10-01"
    )
    try {
        $startTime = (Get-Date).AddHours(-24).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')
        $endTime = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')
        $timespan = "$startTime/$endTime"
        Write-Verbose "Evaluating timespan: $timespan"
        $uri = "https://management.azure.com$resourceId/providers/Microsoft.Insights/metrics?api-version=$apiVersion&metricnames=$metricNames&aggregation=maximum&interval=PT1M&timespan=$timespan"
        $headers = @{ "Authorization" = "Bearer $accessToken"; "Content-Type" = "application/json" }
        
        $response = Invoke-RestMethod -Uri $uri -Headers $headers -Method Get
        if ($response) {
            Write-Verbose "API response successfully retrieved."
            return $response
        } else {
            Write-Error "No response from API."
        }
    } catch {
        Write-Error "Error retrieving metrics: $_"
    }
}

# Check if data disk latency violates thresholds
function Check-Latency {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [Object]$metrics,

        [Parameter()]
        [int]$latencyThreshold = 500,

        [Parameter()]
        [int]$consecutiveCount = 5
    )
    $violationTimes = @()
    foreach ($metric in $metrics.value) {
        if ($metric.name.value -eq "Data Disk Latency") {
            $count = 0
            foreach ($dataPoint in $metric.timeseries[0].data) {
                if ($dataPoint.maximum -gt $latencyThreshold) {
                    $count++
                    if ($count -ge $consecutiveCount) {
                        $violationTimes += $dataPoint.timeStamp
                        $count = 0  # Reset count after recording a violation
                    }
                } else {
                    $count = 0  # Reset count if the sequence is broken
                }
            }
        }
    }
    if ($violationTimes.Count -gt 0) {
        Write-Verbose "Latency violations detected."
        return @{ "Flag" = $true; "Times" = $violationTimes }
    } else {
        Write-Verbose "No latency violations detected."
        return @{ "Flag" = $false }
    }
}

# Check metrics other than latency to evaluate for throttling
function Check-OtherMetricsThrottled {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [Object]$metrics,

        [Parameter()]
        [int]$PercentageThreshold = 90,

        [Parameter()]
        [int]$consecutiveCount = 5
    )
    $violatedMetrics = @()
    foreach ($metric in $metrics.value) {
        $count = 0
        foreach ($dataPoint in $metric.timeseries[0].data) {
            if ($dataPoint.maximum -gt $PercentageThreshold) {
                $count++
                if ($count -ge $consecutiveCount) {
                    $violatedMetrics += @{ "Metric" = $metric.name.localizedValue; "Time" = $dataPoint.timeStamp; "Value" = $dataPoint.maximum }
                    break
                }
            } else {
                $count = 0
            }
        }
    }
    if ($violatedMetrics.Count -gt 0) {
        Write-Verbose "Other metrics violations detected."
    } else {
        Write-Verbose "No other metrics violations detected."
    }
    return $violatedMetrics
}

# Compare times for latency & other throttled metrics. Logs the volations with values & timestamps
function CompareTimes {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [Hashtable]$latencyResult,
        
        [Parameter(Mandatory = $true)]
        [Array]$otherMetrics
    )
    foreach ($metric in $otherMetrics) {
        $otherDateTime = [DateTime]$metric["Time"]
        $isWithinFiveMinutes = $false
        $closestLatencyTime = $null
        $closestTimeDifference = [int]::MaxValue

        foreach ($latencyTime in $latencyResult.Times) {
            $latencyDateTime = [DateTime]$latencyTime
            $timeDifference = [Math]::Abs(($otherDateTime - $latencyDateTime).TotalMinutes)
            
            if ($timeDifference -le 5) {
                $isWithinFiveMinutes = $true
                if ($timeDifference -lt $closestTimeDifference) {
                    $closestTimeDifference = $timeDifference
                    $closestLatencyTime = $latencyTime
                }
            }
        }

        if ($isWithinFiveMinutes) {
            if ($otherDateTime -lt $closestLatencyTime) {
                Write-Host "`n $($metric["Metric"]) limit was hit before latency spiked at $closestLatencyTime with value $($metric["Value"]). `n"
            } else {
                Write-Host "`n $($metric["Metric"]) hit its limit with value $($metric["Value"]) at $($metric["Time"])."
                Write-Host "Latency spiked at $closestLatencyTime before $($metric["Metric"]) hit its limit `n"
            }
        } else {
            Write-Host "`n Metric: $($metric["Metric"]) exceeded its threshold with a value of $($metric["Value"]) at $($metric["Time"]), but this was not within 5 minutes of any latency spikes."
        }
    }
}

# Prompt user for latency threshold
$latencyThreshold = Read-Host "Enter Latency Threshold (default is 500)"
if (-not [int]::TryParse($latencyThreshold, [ref]0)) {
    $latencyThreshold = 500 # Use default if invalid input
    Write-Host "No valid input provided. Using Default 500ms for disk latency threshold"
}

# Execute main logic
$latencyMetrics = Get-Metrics -accessToken $accessToken -resourceId $resourceId -metricNames "Data Disk Latency"
$latencyResult = Check-Latency -metrics $latencyMetrics -latencyThreshold $latencyThreshold

if ($latencyResult.Flag) {
    
    # If latency is flagged, check for other metrics. If there is no disk latency, machine is likely not throttled but only at high consumption
    Write-Verbose "Checking the following metrics: Data Disk Bandwidth Consumed Percentage,Data Disk IOPS Consumed Percentage,VM Cached Bandwidth Consumed Percentage,VM Cached IOPS Consumed Percentage,VM Uncached Bandwidth Consumed Percentage,VM Uncached IOPS Consumed Percentage"
    
    $DiskVMMetrics = Get-Metrics -accessToken $accessToken -resourceId $resourceId -metricNames "Data Disk Bandwidth Consumed Percentage,Data Disk IOPS Consumed Percentage,VM Cached Bandwidth Consumed Percentage,VM Cached IOPS Consumed Percentage,VM Uncached Bandwidth Consumed Percentage,VM Uncached IOPS Consumed Percentage"
    
    $additionalMetrics = Check-OtherMetricsThrottled -metrics $DiskVMMetrics
    
    if ($additionalMetrics.Count -gt 0) {
        CompareTimes $latencyResult $additionalMetrics
    } else {
        Write-Host "No metrics violations detected besides latency."
    }
} else {
    Write-Host "No latency issues detected."
}

Sonraki adımlar