Azure の仮想マシンでディスクのスループットを向上させる方法として、複数のデータディスクを使用して記憶域プールでディスクを構成する方法があるかと思います。
記憶域プールでは、あとからプールにディスクを足し、ディスクの容量を拡張することができますが、SQL Server のログファイルの用途で使用するディスクについて、性能を向上させるためにあとからディスクを足すのは効果的ではない可能性がありますので、その点についてまとめてみたいと思います。
まずは、以下のような PowerShell のスクリプトでデータディスクが一つ接続された仮想マシンを作成してみます。
この投稿の検証をするためには 2 本以上のデータディスクが接続できる仮想マシンの必要があります。
$AdminUser = "" $AdminPassword = "" $ServiceName = "" # クラウドサービス名のため取得できるサービス名を指定 $Location = "japan west" # 仮想マシンを作成するロケーションを指定 $TimeZone = "Tokyo Standard Time" # TimeZone $VMName = "VDiskTest" # サブスクリプションの選択 if ($Subscription -eq $null){ Add-AzureAccount $Subscription = Get-AzureSubscription | Out-GridView -OutputMode Single Select-AzureSubscription $Subscription.SubscriptionName -Current # CurrentStorageAccount が設定されていない場合は以下で設定 # Set-AzureSubscription -SubscriptionName $Subscription.SubscriptionName -CurrentStorageAccountName "" } $InstanceSize = @( @("Basic","Basic_A0","1","768GB","1"), @("Basic","Basic_A1","1","1.75GB","2"), @("Basic","Basic_A2","2","3.5GB","4"), @("Basic","Basic_A3","4","7GB","8"), @("Basic","Basic_A4","8","16GB","16"), @("Standard","ExtraSmall","1","768MB","1"), @("Standard","Small","1","1.75GB","2"), @("Standard","Medium","2","3.5GB","4"), @("Standard","Large","4","7GB","8"), @("Standard","ExtraLarge","8","14GB","16"), @("Standard","A5","2","14GB","4"), @("Standard","A6","4","28GB","8"), @("Standard","A7","8","56GB","16"), @("Standard","A8","8","56GB","16"), @("Standard","A9","16","112GB","16"), @("Standard","Standard_D1","1","3.5GB","2"), @("Standard","Standard_D2","2","7GB","4"), @("Standard","Standard_D3","4","14GB","8"), @("Standard","Standard_D4","8","28GB","16"), @("Standard","Standard_D11","2","14GB","4"), @("Standard","Standard_D12","4","28GB","8"), @("Standard","Standard_D13","8","56GB","16"), @("Standard","Standard_D14","16","112GB","32") ) | %{ [PSCustomObject]@{ Plan = $_[0] Size = $_[1] CPU_Core = $_[2] Memory = $_[3] DataDisk = $_[4] } } | Out-GridView -OutputMode Single # Windows Server 2012 R2 の最新のイメージを取得 $image = Get-AzureVMImage | where {$_.OS -eq "Windows" -and $_.ImageFamily -eq "Windows Server 2012 R2 Datacenter"} | sort PublishDate -Descending | select -First 1 # AzureVM の基本設定 $VMConfig = New-AzureVMConfig -Name $VMName -InstanceSize $InstanceSize.Size -ImageName $image.ImageName Add-AzureProvisioningConfig -VM $VMConfig -Windows -AdminUsername $AdminUser -Password $AdminPassword -TimeZone $TimeZone # 1 本のデータディスクを追加 $VMConfig = $VMConfig | Add-AzureDataDisk -CreateNew -DiskLabel "Data Disk 01" -DiskSizeInGB 100 -LUN 1 -HostCaching None # NW 設定 $VNetSite = Get-AzureVNetSite | Out-GridView -OutputMode Single # プライマリ NIC の選択 $VMNW = @() $VMNW += $VNetSite.Subnets | Out-GridView -OutputMode Single # 既定の NIC の設定 Set-AzureSubnet -SubnetNames $VMNW[0].Name -VM $VMConfig # 仮想マシンの作成 New-AzureVM -ServiceName $ServiceName -Location $Location -VNetName $VNetSite.Name -WaitForBoot -VMs $VMConfig
作成が終了したら、仮想マシンにログインし以下の PowerShell で記憶域スペースのディスクを作成します。
$StoragePoolName = "SQL Server Database Disk Pool" $VirtualDiskName = "SQL Server Database Disk" # ストレージプールを追加するストレージサブシステムを取得 $StorageSubSystem = Get-StorageSubSystem # ストレージプールに追加する接続したデータディスクを取得 $PhysicalDisks = Get-PhysicalDisk | where CanPool -eq $true # ストレージプールの作成 $StoragePool = New-StoragePool -PhysicalDisks $PhysicalDisks -FriendlyName $StoragePoolName -StorageSubSystemFriendlyName $StorageSubSystem.FriendlyName # 仮想ディスクの作成 $VirtualDisk = New-VirtualDisk -StoragePoolFriendlyName $StoragePool.FriendlyName -FriendlyName $VirtualDiskName -ResiliencySettingName Simple -ProvisioningType Fixed -UseMaximumSize -Interleave 64KB # ディスクのフォーマット $Disk = Get-Disk | where PartitionStyle -eq "RAW" $Disk | Initialize-Disk $Partition = $Disk | New-Partition -UseMaximumSize $Partition | Set-Partition -NewDriveLetter "F" Start-Sleep 1 $Partition | Format-Volume -FileSystem NTFS -Confirm:$false -AllocationUnitSize 65536 -Force
このディスクに対して、SQLIO を実行した結果が以下になります。
1 本のデータディスクに対して I/O を発生させていますので 500IOPS となっていますね。
# この環境、Basic なのに 500IOPS 出てるのですよね。
次に Azure の PowerShell で仮想マシンにデータディスクを追加します。
# 仮想マシンを作成した PowerShell の続きで実行しています。
$VM = Get-AzureVM -ServiceName $ServiceName -Name $VMName Add-AzureDataDisk -CreateNew -DiskLabel "Data Disk 02" -DiskSizeInGB 100 -LUN 2 -HostCaching None -VM $VM | Update-AzureVM
これでデータディスクが追加されましたので、記憶域スペースにディスクを追加して、作成してある仮想ディスクに追加したディスクの容量を割り当てます。
# ディスクの追加 $StoragePoolName = "SQL Server Database Disk Pool" $VirtualDiskName = "SQL Server Database Disk" # ストレージプールにディスクを追加 $PhysicalDisks = Get-PhysicalDisk | where CanPool -eq $true Add-PhysicalDisk -StoragePoolFriendlyName $StoragePoolName -PhysicalDisks $PhysicalDisks $PoolSize = Get-VirtualDiskSupportedSize -StoragePoolFriendlyName $StoragePoolName -ResiliencySettingName Simple # ディスクの拡張 $VirtualDisk = Get-VirtualDisk -FriendlyName $VirtualDiskName $VirtualDisk | Resize-VirtualDisk -Size ($VirtualDisk.size + $PoolSize.VirtualDiskSizeMax) # パーティションの拡張 Get-PartitionSupportedSize -DriveLetter F | Out-Null $Partition = Get-PartitionSupportedSize -DriveLetter F Resize-Partition -DriveLetter F -Size $Partition.SizeMax
これにより、ディスクが拡張され、今回のスクリプトの場合では 100GB → 200GB に拡張が行われ、使用できるディスク領域が増加しています。
この状態で SQLIO を実行するとどうなるかを試してみます。
負荷をかけるディスクとしては 2 本で構成されている形になります。
500IOPS しか発生できていないことが確認できますね。
仮想ディスクを作成した際には、「NumberOfColumns」(列数) を設定しないで作成しています。
それでは、この仮想ディスクの列数が何で作成されているのかを以下のコマンドで確認してみます。
$VirtualDiskName = "SQL Server Database Disk" Get-VirtualDisk -FriendlyName $VirtualDiskName | select NumberOfColumns
列数が「1」で作成されているのが確認できますね。
このため、データは 1 個のディスクに分散されて書き込まれる→複数のディスクに分散して書き込みが行われないことになり、複数のデータディスクで記憶域スペースを構成してもディスクI/Oが向上しない状態となります。
- 仮想ディスクを作成する際に、記憶域スペースに含まれているディスク数を上限に設定ができる
ことになります。
そのため、仮想ディスクを作成した後に、データディスクを追加しても、仮想ディスクを作成した際の列数で書き込みが分散されるため、複数のデータディスクで構成していても I/O が向上しない形になります。
SQL Server のデータファイルであれば、複数のデータファイルを複数のディスクに分散させて配置することで I/O を向上させることができますが、ログファイルに関してはシーケンシャルに書き込みが行われるため、複数のファイルで構成して配置するディスクを分散させても、I/O 効率が上昇しません。
ログファイルを配置するディスクについては、単体のディスク I/O が性能にダイレクトに影響してくる形になります。
仮想ディスクの列数は作成後は変更できないため、
- ログファイルを配置する仮想ディスクを作成する際には、複数のディスクで作成し、列数を適切に設定しておく
ことが重要となってくるかと思います。
先ほどの仮想ディスクの作成のスクリプトをデータディスクを 2 本接続した状態で SQLIO を実行してみます。
この場合、列数が 2 で設定されますので、2 本文のデータディスクの I/O を発生させることができています。
列数ですが以前投稿した Azure VM で記憶域プールを使用した際の列数の影響について で投稿しましたが、複数のデータディスクを接続した場合、明示的に指定をしなかった場合は、8 本以上のデータディスクを接続していても 8 にデフォルトで設定されてしまいますので、こちらも合わせて注意をしておくとよいかと。
また、インスタンスのサイズによって接続できるデータディスクの本数が異なってきますので、スケールダウンして運用をしたい場合などは、接続しているデータディスクの本数が影響してスケールダウンできない可能性がありますので、最初に大量のデータディスクで仮想ディスクを構築した場合などは、将来、スケールダウンすることがあるかを考慮する必要があるかと。