メモリは、パフォーマンスの三角形を形成するリソースの1つであり、CPUとストレージが他の2つです。 1つがヒットした場合、他の2つは負荷をかけてパフォーマンスを許容レベルに引き上げようとしますが、常にトレードオフがあります。トランザクションをメモリにコミットできない場合は、SQLServerによってディスクサブシステムに転送されます。これにより、パフォーマンスのボトルネックが発生します。したがって、待機統計はSQLServerのパフォーマンスの問題を特定するのに役立ちます。
この記事では、次のトピックについて説明します。
- SQLServerのメモリ設定と構成の内部を理解する
- SQLServerメモリとそのデータベースおよびアプリケーションのパフォーマンスへの影響
- メモリ使用量に寄与するさまざまなSQLServerコンポーネントについて説明します
- メモリサイズ設定のベストプラクティスと推奨事項
- マルチサーバーメモリレポート
- その他…
メモリ管理の内部
SQL Serverには、システムのワークロードに基づいて自動化された動的メモリ管理を実行するメモリ管理ユニットがあります。このメモリは、今日のビジネス–技術ニーズにとって重要な揮発性のスペースであり、その適切なサイズ設定は、アプリケーションの最適なパフォーマンスに不可欠です。
ただし、サーバーをセットアップするときに、サイズ設定にいくつかのデフォルト値が含まれていることは誰もが知っています。場合によっては、データベースに目に見えるアクティビティがないにもかかわらず、SQL Serverがサーバー上のほとんどすべてのメモリを使用していることがすぐにわかり、次の質問が発生します。デフォルト値は正しくありませんか?もしそうなら、適切なサイズは何ですか?
SQL Serverのメモリ管理は、Fill-and-Flushアルゴリズムで機能します。デフォルト値では、オペレーティングシステムからの要求がない限り、メモリ消費量の増加は制限されません。
サイズ設定は、システムのさまざまなコンポーネントによって異なります。多くの場合、70%から80%の間に設定することをお勧めします。次に、それを監視して、他に何が欠けている可能性があるか、および設定を微調整する必要があるかどうかを確認する必要があります。 SQL Serverに他のサービスがある場合(実際にはそうすべきではありません)、特にこれらのサービスがメモリを大量に消費している場合は、さらに多くのサービスを残す必要があります。次のいずれかのシナリオで、SQLインスタンスのメモリ設定を再検討することを検討してください。
- オペレーティングシステムの無反応
- アプリケーションの枯渇
- 大容量のメモリバッファを必要とするバックアップ操作
- インメモリ最適化オブジェクト
- インデックスのメンテナンスを実行するには大量のメモリが必要になるため、列ストアインデックス。
SQLServerのメモリ設定は非常に簡単です。 sp_configureを使用して値を変更できます またはSSMSGUI。これはオンラインオプションですが、これらの値を設定またはリセットすると、一部の内部キャッシュオブジェクトが再シャッフルされ、システムの実行速度がわずかに低下する可能性があることに注意してください。
sp_configure「最大サーバーメモリ(MB)」、<メモリ(MB)>
この場合、数値「2147483647」は、SQL Serverに上限がなく、サーバー上のすべてのメモリを使用することを意味します。
最小サーバーメモリ:フロア値としての最小サーバーメモリ。 SQL Serverは、サーバーの最小メモリ設定に達するまで、メモリを独自に使用するためにコミットします。その後、少なくともこの量の使用可能なメモリを維持します。
最大サーバーメモリ:最小サーバーメモリがフロアを提供するのと同じように、最大サーバーメモリが上限を提供します。
最小および最大メモリレベルは、バッファプールで使用できるメモリ量の下限と上限です。バッファプールは、SQLServerによって消費されるメモリの最大のチャンクです。以下は、バッファプールのメモリを使用するSQLインスタンス内のSQLServerコンポーネントです
- データベースページキャッシュ
- 内部ログキャッシュ
- プロシージャキャッシュまたはクエリプランキャッシュ
- クエリワークロードスペース
- ロック(メモリ付与)
- 接続コンテキスト
- クエリの最適化
- システムレベルのデータ構造
Available Mbytes、Pages / Sec、Buffer Cache Hit Ratio、PLEなどの重要なメトリックの値によって、SQLServerのパフォーマンスが決まります。
バッファキャッシュヒット率は、各アプリケーションに固有です。通常、90%が望ましいと考えられています。これは、リクエストの90%以上がキャッシュによって処理されたことを意味します。これは、良いことです。値が低い場合は、常に90%を超えるまでメモリを追加します。
使用可能なバイト数は、使用可能なメモリの量を示すものにすぎません。 Pages / secカウンターは、ハードページフォールトが原因でディスクから取得された、またはディスクに書き込まれたページ数を示します。
PLEはPageLifeExpectancyの略で、ページがプールにとどまる秒数を示します。
たとえば、
$server = 'hqdbt01'
$counters = @("\Memory\Available MBytes",
"\Memory\Pages/sec",
"\SQLServer:Buffer Manager\Buffer cache hit ratio",
"\SQLServer:Buffer Manager\Lazy writes/sec",
"\SQLServer:Buffer Manager\Page life expectancy"
)
$collections = Get-Counter -ComputerName $server -Counter $counters -SampleInterval 10 -MaxSamples 1
Write-Output $collections
foreach ($collection in $collections)
{$sampling = $collection.CounterSamples | Select-Object -Property TimeStamp, Path, Cookedvalue
$sampling | Format-Table -AutoSize
}
推奨事項とベストプラクティス
ここで、メモリのサイズを決定する手法を簡単に見てみましょう。
- オペレーティングシステム用に予約された1GBのメモリ
- 最初の4GB、最大16GBのRAMの後は4GBのRAMごとにそれぞれ1GB
- 16GBを超えるRAMの8GBごとに1GB
たとえば、32 GBのRAMデータベースサーバーがある場合、オペレーティングシステムに割り当てられるメモリは次のようになります
- 1 GB、最小割り当て
- + 3 GB、16 GB – 4 GB =12 GB; 12GBを4GBで割ると(各4GBは1GBになります)、3GBになります。
- + 2 GB、32 GB – 16 GB =16 GB; 16を8で割ると(16GBが1GBになった後、各8 GB)は2GBになります
したがって、合計で32 GBのRAMを搭載したサーバーの場合、7GBがオペレーティングシステム用に予約されます。これは、SQLServerに割り当てられる最大メモリが25GBである必要があります。同様に、64 GBサーバーの場合、オペレーティングシステム用に10 GBを予約し、SQLServer用に54GBを割り当てる必要があります。
ある時点で、Windows Management Instrumentation(WMI)について聞いたり、使用したりしたことがあります。 WMIにはいくつかのクラスがあり、ハードウェア、インストールされているソフトウェア、オペレーティングシステム、さらにはレジストリに関する情報を抽出できます。設定を変更したり、これらの側面でアクションを実行したりすることもできます。
win32_OperatingSystemクラスは、アクティブに関する必要なすべての情報を含むWMIクラスです。 オペレーティングシステム(たとえば、デュアルブートの場合)。このクラスは、オペレーティングシステムに割り当てられているメモリの量を取得するためにも使用できます。クラスが返すことができるオブジェクトのいくつかを次に示します。これは私たちに役立つ可能性があります(メモリはこのクラスによってキロバイト単位で測定されます):
- TotalVisibleMemorySize :このフィールドには、オペレーティングシステムがアクセスできる物理メモリの合計が表示されます。アクセスできないメモリのチャンクにより、インストールされている数よりも小さい数がここに表示される場合があります。
- FreePhysicalMemory :これにより、空きの物理メモリの量がわかります。
- TotalVirtualMemorySize :これは、OSが使用できる仮想メモリの合計です。これには、コンピュータにインストールされている物理メモリと、ページファイルのサイズが含まれます。
- FreeVirtualMemory :FreePhysicalMemoryに似ていますが、ページングメモリにも空き領域が含まれています。
$server='hqdbt01'
Get-WmiObject -Class Win32_OperatingSystem -ComputerName $server | select CSName,
@{name="TotalVirtualMemorySize";expression={($_.TotalVirtualMemorySize/1024).tostring("N0")}},
@{name="TotalVisibleMemorySize";expression={($_.TotalVisibleMemorySize/1024).tostring("N0")}},
@{name="FreePhysicalMemory";expression={($_.FreePhysicalMemory/1024).tostring("N0")}},
@{name="FreeVirtualMemory";expression={($_.FreeVirtualMemory/1024).tostring("N0")}},
@{name="FreeSpaceInPagingFiles";expression={($_.FreeSpaceInPagingFiles/1024).tostring("N0")}},
NumberofProcesses,
NumberOfUsers
Win32_PageFileSettingWMIクラスを使用してページファイル情報を取得できます。
$server='hqdbt01'
Get-WMIObject Win32_PageFileSetting -Computer $server| select @{name="ServerName";expression={$_.__Server}}, Name, InitialSize, MaximumSize
次のクエリは、SQLインスタンスの高レベルのメモリ使用量の詳細を示します。
SELECT
physical_memory_in_use_kb/1024 Physical_memory_in_use_MB,
large_page_allocations_kb/1024 Large_page_allocations_MB,
locked_page_allocations_kb/1024 Locked_page_allocations_MB,
virtual_address_space_reserved_kb/1024 VAS_reserved_MB,
virtual_address_space_committed_kb/1024 VAS_committed_MB,
virtual_address_space_available_kb/1024 VAS_available_MB,
page_fault_count Page_fault_count,
memory_utilization_percentage Memory_utilization_percentage,
process_physical_memory_low Process_physical_memory_low,
process_virtual_memory_low Process_virtual_memory_low
FROM sys.dm_os_process_memory;
スクリプトを準備する
前述の3つの出力を1つのメモリ出力に統合しましょう:
- カウンタを使用したSQL内部メモリ構造
- WMIオブジェクトを使用して利用可能な仮想メモリと物理メモリ
- WMIを使用したページファイルの設定
HTMLコンテンツの準備とは、スクリプトのさまざまなセクションから供給された値を、適切なタグの間に入力することです。
スクリプトは有効なHTMLタグを作成できます。スクリプトで使用される関数は次のとおりです。
- writeHTMLHeader:この関数は、ヘッダーを生成し、HTMLファイルのスタイルを定義するために使用されます。
- writetableFooter:これは終了HTMLタグを定義します。
- writeTableHeader:これはHTMLファイルの13列の出力見出しを定義します
- writeMemoryInfo:これは、2つのWMIクラス出力のマージを実行する関数です。 Win32_PageFileSetting、Win32_OperatingSystem、およびSMO SQLの出力は、この関数の引数として渡されます。このセクションでは、値をさらに変換または操作することもできます。
- メールセクション
[expand title =” Code”]
# First, let’s create a text file, where we will later save memory details $MailServer='mail01.example.com' $MemoryFileName = "f:\PowerSQL\Memory.htm" New-Item -ItemType file $MemoryFileName -Force # Function to write the HTML Header to the file Function writeHtmlHeader { param($fileName) $date = ( get-date ).ToString('yyyy/MM/dd') Add-Content $fileName "<html>" Add-Content $fileName "<head>" Add-Content $fileName "<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'>" Add-Content $fileName '<title>SQLShack Memory Usage Report </title>' add-content $fileName '<STYLE TYPE="text/css">' add-content $fileName "<!--" add-content $fileName "td {" add-content $fileName "font-family: Tahoma;" add-content $fileName "font-size: 11px;" add-content $fileName "border-top: 1px solid #999999;" add-content $fileName "border-right: 1px solid #999999;" add-content $fileName "border-bottom: 1px solid #999999;" add-content $fileName "border-left: 1px solid #999999;" add-content $fileName "padding-top: 0px;" add-content $fileName "padding-right: 0px;" add-content $fileName "padding-bottom: 0px;" add-content $fileName "padding-left: 0px;" add-content $fileName "}" add-content $fileName "body {" add-content $fileName "margin-left: 5px;" add-content $fileName "margin-top: 5px;" add-content $fileName "margin-right: 0px;" add-content $fileName "margin-bottom: 10px;" add-content $fileName "" add-content $fileName "table {" add-content $fileName "border: thin solid #000000;" add-content $fileName "}" add-content $fileName "-->" add-content $fileName "</style>" Add-Content $fileName "</head>" Add-Content $fileName "<body>" add-content $fileName "<table width='100%'>" add-content $fileName "<tr bgcolor='#CCCCCC'>" add-content $fileName "<td colspan='13' height='25' align='center'>" add-content $fileName "<font face='tahoma' color='#003399' size='4'><strong>SQLShack Memory Usage Report - $date</strong></font>" add-content $fileName "</td>" add-content $fileName "</tr>" add-content $fileName "</table>" } # Function to write the HTML Header to the file Function writeTableHeader { param($fileName) Add-Content $fileName "<tr bgcolor=#CCCCCC>" Add-Content $fileName "<td width='10%' align='center'>ServerName</td>" Add-Content $fileName "<td width='10%' align='center'>TotalVirtualMemorySize</td>" Add-Content $fileName "<td width='10%' align='center'>TotalVisibleMemorySize</td>" Add-Content $fileName "<td width='10%' align='center'>FreePhysicalMemory</td>" Add-Content $fileName "<td width='10%' align='center'>FreeVirtualMemory</td>" Add-Content $fileName "<td width='10%' align='center'>FreeSpaceInPagingFiles</td>" Add-Content $fileName "<td width='10%' align='center'>NumberofProcesses</td>" Add-Content $fileName "<td width='10%' align='center'>NumberOfUsers</td>" Add-Content $fileName "<td width='10%' align='center'>PageFile</td>" Add-Content $fileName "<td width='10%' align='center'>Page-InitialSize</td>" Add-Content $fileName "<td width='10%' align='center'>Page-MaxSize</td>" Add-Content $fileName "<td width='10%' align='center'>SQLMaxMemory</td>" Add-Content $fileName "<td width='10%' align='center'>SQLMinMemory</td>" Add-Content $fileName "<td width='10%' align='center'>Memory Available MBytes</td>" Add-Content $fileName "<td width='10%' align='center'>Buffer Cache Hit Ratio</td>" Add-Content $fileName "<td width='10%' align='center'>PLE</td>" Add-Content $fileName "</tr>" } Function writeHtmlFooter { param($fileName) Add-Content $fileName "</body>" Add-Content $fileName "</html>" } Function writeMemoryInfo { param($filename,$csname,$TotalVirtualMemorySize,$TotalVisibleMemorySize,$FreePhysicalMemory,$FreeVirtualMemory,$FreeSpaceInPagingFiles,$NumberofProcesses,$NumberOfUsers,$PageFile,$initialSize,$MaxSize,$SQLMaxMemory, $SQLMinMemory ,$mAvailableMBytes, $Buffercachehitratio, $PLE ) Add-Content $fileName "<tr>" Add-Content $fileName "<td>$csname </td>" Add-Content $fileName "<td>$TotalVirtualMemorySize </td>" Add-Content $fileName "<td>$TotalVisibleMemorySize</td>" Add-Content $fileName "<td>$FreePhysicalMemory </td>" Add-Content $fileName "<td>$FreeVirtualMemory </td>" Add-Content $fileName "<td>$FreeSpaceInPagingFiles </td>" Add-Content $fileName "<td>$NumberofProcesses </td>" Add-Content $fileName "<td>$NumberOfUsers</td>" Add-Content $fileName "<td>$PageFile</td>" Add-Content $fileName "<td>$initialSize</td>" Add-Content $fileName "<td>$MaxSize</td>" Add-Content $fileName "<td>$SQLMaxMemory</td>" Add-Content $fileName "<td>$SQLMinMemory</td>" Add-Content $fileName "<td>$mAvailableMBytes</td>" Add-Content $fileName "<td>$Buffercachehitratio</td>" Add-Content $fileName "<td>$PLE</td>" Add-Content $fileName "</tr>" } Function sendEmail { param($from,$to,$subject,$smtphost,$htmlFileName) $body = Get-Content $htmlFileName $body = New-Object System.Net.Mail.MailMessage $from, $to, $subject, $body $body.isBodyhtml = $true $smtpServer = $MailServer $smtp = new-object Net.Mail.SmtpClient($smtpServer) $smtp.Send($body) } writeHtmlHeader $MemoryFileName Add-Content $MemoryFileName "<table width='100%'><tbody>" Add-Content $MemoryFileName "<tr bgcolor='#CCCCCC'>" Add-Content $MemoryFileName "<td width='100%' align='center' colSpan=16><font face='tahoma' color='#003399' size='2'><strong> Memory Usage Details</strong></font></td>" Add-Content $MemoryFileName "</tr>" writeTableHeader $MemoryFileName foreach ($svr in get-content "\\hqdbsp18\f$\PowerSQL\Server.txt"){ $page=Get-WMIObject Win32_PageFileSetting -Computer $svr| select __Server, Name, InitialSize, MaximumSize $dp = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $svr | select CSName, @{name="TotalVirtualMemorySize";expression={($_.TotalVirtualMemorySize/1024).tostring("N0")}}, @{name="TotalVisibleMemorySize";expression={($_.TotalVisibleMemorySize/1024).tostring("N0")}}, @{name="FreePhysicalMemory";expression={($_.FreePhysicalMemory/1024).tostring("N0")}}, @{name="FreeVirtualMemory";expression={($_.FreeVirtualMemory/1024).tostring("N0")}}, @{name="FreeSpaceInPagingFiles";expression={($_.FreeSpaceInPagingFiles/1024).tostring("N0")}}, NumberofProcesses, NumberOfUsers $srv = new-object ('Microsoft.SqlServer.Management.Smo.Server') ($svr) write-host $srv.Configuration.MaxServerMemory.RunValue write-host $srv.Configuration.MinServerMemory.RunValue $counters = @("\Memory\Available MBytes", "\Memory\Pages/sec", "\SQLServer:Buffer Manager\Buffer cache hit ratio", "\SQLServer:Buffer Manager\Lazy writes/sec", "\SQLServer:Buffer Manager\Page life expectancy" ) $collections = Get-Counter -ComputerName $svr -Counter $counters -SampleInterval 5 -MaxSamples 1 Write-Output $collections foreach ($collection in $collections) { $sampling = $collection.CounterSamples | Select-Object -Property TimeStamp, Path, Cookedvalue foreach($sam in $sampling) { if ($sam.Path -like "*\Memory\Available MBytes*") { $mAvailableMBytes=$sam.CookedValue } elseif ($sam.Path -like "*Buffer Manager\Buffer cache hit ratio*") { $Buffercachehitratio=$sam.CookedValue } elseif ($sam.Path -like "*Page life expectancy*") { $PLE=$sam.CookedValue} } } write-host $mAvailableMBytes $Buffercachehitratio $PLE Write-Host $dp.csname $dp.TotalVirtualMemorySize $dp.TotalVisibleMemorySize $dp.FreePhysicalMemory $dp.FreeVirtualMemory $dp.FreeSpaceInPagingFiles $dp.NumberofProcesses $dp.NumberOfUsers $page.InitialSize $page.Name $page.MaximumSize $srv.Configuration.MaxServerMemory.RunValue $srv.Configuration.MinServerMemory.RunValue $mAvailableMBytes $Buffercachehitratio $PLE writeMemoryInfo $MemoryFileName $dp.csname $dp.TotalVirtualMemorySize $dp.TotalVisibleMemorySize $dp.FreePhysicalMemory $dp.FreeVirtualMemory $dp.FreeSpaceInPagingFiles $dp.NumberofProcesses $dp.NumberOfUsers $page.Name $page.InitialSize $page.MaximumSize $srv.Configuration.MaxServerMemory.RunValue $srv.Configuration.MinServerMemory.RunValue $mAvailableMBytes $Buffercachehitratio $PLE } Add-Content $MemoryFileName "</table>" writeHtmlFooter $MemoryFileName $date = ( get-date ).ToString('yyyy/MM/dd') sendEmail [email protected] [email protected] "Memory Usage Report - $Date" $MailServer $MemoryFileName
[/エキスパンド]
出力
まとめ
SQL Serverのメモリ管理についていくつかの新しいことを学んだので、SQLServerのリソースをよりよく理解できるようになります。
サーバーに十分なRAMがある場合、データページのバッファプールでの寿命が長くなる可能性があり、その結果、I/Oのニーズが大幅に削減されます。
ほとんどの場合、データベース管理者はデフォルトのメモリ設定に依存していますが、メモリ要件の内部はインスタンスのワークロードに依存することを理解する必要があります。
この記事は、SQLServerメモリとその内部の概要です。また、最大メモリを設定しないことによって引き起こされるパフォーマンスのボトルネックの背後にあるさまざまな理由についても説明します。
メモリレポートを設定および構成するためのステップバイステップの手順を含めました。 SQLメモリを設定する方法の手順も含まれています。さらに、SQLServer環境で使用可能なメモリの使用に寄与するさまざまなSQLコンポーネントについて説明しました。
覚えておくべき1つのポイントは、メモリの割り当てと割り当て解除により起動が遅くなることです。したがって、同じサーバー上で複数のアプリケーションを停止および開始する場合、パフォーマンスに影響を与える可能性があります。同様に、同じサーバー上で他の複数のアプリケーションが実行されている場合、最適なパフォーマンスを確保するには、最小サーバーメモリと最大サーバーメモリの設定がより重要になります。
今のところこれですべてです…
参考資料
- メモリ使用量の監視
- SQLServerで最大サーバーメモリを設定することの重要性とその設定方法
- サーバーメモリサーバー構成オプション