Geheugen is een van de bronnen die de prestatiedriehoek vormen - CPU en opslag zijn de andere twee. Als er een wordt geraakt, nemen de andere twee de last om te proberen de prestaties op een acceptabel niveau te brengen, maar er is altijd een afweging. Alle transacties die niet in het geheugen kunnen worden vastgelegd, worden door SQL Server doorgestuurd naar het schijfsubsysteem. Dit zorgt voor een performance bottleneck. Daarom kunnen de wachtstatistieken helpen bij het identificeren van prestatieproblemen op een SQL Server.
In dit artikel worden de volgende onderwerpen besproken:
- Inzicht in de interne aspecten van de geheugeninstelling en configuratie van SQL Server
- Het SQL Server-geheugen en de impact ervan op de database- en applicatieprestaties
- Bespreek verschillende SQL Server-componenten die bijdragen aan het geheugengebruik
- Beste praktijken en aanbevelingen voor geheugengrootte
- Multi-server geheugenrapport
- En meer...
Intern geheugenbeheer
SQL Server heeft een geheugenbeheereenheid die geautomatiseerd dynamisch geheugenbeheer uitvoert op basis van de werkbelasting van het systeem. Dit geheugen is de vluchtige ruimte die van cruciaal belang is voor de hedendaagse zakelijke - technische behoeften, waarvan de juiste grootte essentieel is voor de optimale prestaties van de applicaties.
We weten echter allemaal dat bij het instellen van de server de grootte enkele standaardwaarden bevat. in sommige gevallen komen we er al snel achter dat SQL Server bijna al het geheugen op de server gebruikt, ook al is er geen zichtbare activiteit op de databases, wat de vragen oproept:Zijn de standaardwaarden onjuist? Zo ja, wat moet dan de juiste maat zijn?
Geheugenbeheer op SQL Server werkt op het Fill-and-Flush-algoritme. De standaardwaarden beperken de groei van het geheugengebruik niet, tenzij er een verzoek is van het besturingssysteem.
De maatvoering hangt af van verschillende componenten van het systeem. In veel gevallen is een instelling tussen 70% en 80% een goed uitgangspunt. Vervolgens moet u het ook controleren om te zien wat u nog meer mist en of u de instelling moet aanpassen. Als je andere services op de SQL Server hebt (dat zou je eigenlijk niet moeten doen), moet je misschien meer achterlaten, vooral als deze services geheugenvreters zijn. Overweeg de geheugeninstelling van de SQL-instantie opnieuw te bekijken in een van de volgende scenario's:
- Niet reageren van het besturingssysteem
- Uitputting van de toepassing
- Back-upbewerkingen waarvoor grote geheugenbuffers nodig zijn
- In-memory geoptimaliseerde objecten
- Kolomopslagindexen, omdat ze grote hoeveelheden geheugen nodig hebben om indexonderhoud uit te voeren.
De geheugeninstelling op SQL Server is vrij eenvoudig. U kunt de waarde wijzigen met sp_configure of SSMS GUI. Dit is een online optie, maar onthoud dat het instellen of resetten van deze waarden ertoe kan leiden dat sommige interne cache-objecten opnieuw worden geschud, waardoor het systeem iets langzamer zal werken.
sp_configure ‘max servergeheugen (MB)’,
In dit geval betekent het getal "2147483647" dat SQL Server geen bovengrens heeft en al het geheugen op de server zal gebruiken.
Min servergeheugen:min servergeheugen als minimumwaarde; SQL Server zal geheugen voor eigen gebruik vastleggen totdat het de minimale servergeheugeninstelling bereikt. Daarna behoudt het minstens deze hoeveelheid bruikbaar geheugen.
Max servergeheugen:op dezelfde manier waarop min servergeheugen een bodem biedt, biedt max servergeheugen een plafond.
De minimale en maximale geheugenniveaus zijn de onder- en bovengrens van de hoeveelheid geheugen die door de bufferpool mag worden gebruikt. De bufferpool is het grootste deel van het geheugen dat wordt verbruikt door SQL Server. Hieronder volgen de SQL Server-componenten binnen de SQL-instantie die geheugen uit de bufferpool gebruiken
- Databasepaginacache
- Interne logcaches
- Procedurecache of queryplancache
- Query werkbelasting ruimte
- Vergrendelingen (geheugentoekenningen)
- Verbindingscontext
- Zoekopdrachten optimaliseren
- Gegevensstructuren op systeemniveau
De waarden van de belangrijke metrieken zoals Beschikbare Mbytes, Pages/Sec, Buffer Cache Hit Ratio, PLE, enz. bepalen de prestaties van SQL Server.
Buffer Cache Hit Ratio is specifiek voor elke toepassing. 90% wordt meestal als wenselijk beschouwd. Het betekent dat meer dan 90% van de verzoeken door de cache werden afgehandeld, wat een goede zaak is. Als de waarde lager is, voeg dan meer geheugen toe totdat het constant hoger is dan 90%.
Beschikbare bytes is niets anders dan een indicatie van hoeveel geheugen beschikbaar is voor gebruik. De teller Pagina's/sec laat zien hoeveel pagina's van de schijf zijn opgehaald of naar de schijf zijn geschreven, beide vanwege fouten in de harde pagina.
PLE staat voor Page Life Expectancy, wat aangeeft hoeveel seconden de pagina in de pool blijft.
Bijvoorbeeld,
$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
}
Aanbevelingen en best practices
Laten we nu kort kijken naar de technieken om het geheugen te vergroten.
- 1 GB geheugen gereserveerd voor besturingssysteem
- 1 GB elk voor elke 4 GB RAM na de eerste 4 GB, tot 16 GB RAM
- 1 GB elk voor elke 8 GB in meer dan 16 GB RAM
Als u bijvoorbeeld een 32 GB RAM-databaseserver heeft, zou het geheugen dat aan het besturingssysteem moet worden gegeven, zijn
- 1 GB, de minimale toewijzing
- + 3 GB, sinds 16 GB – 4 GB =12 GB; 12 GB gedeeld door 4 GB (elke 4 GB krijgt 1 GB) is 3 GB.
- + 2 GB, als 32 GB – 16 GB =16 GB; 16 gedeeld door 8 (elke 8 GB na 16 GB krijgt 1 GB) is 2 GB
In totaal wordt dus voor een server met 32 GB RAM 7 GB gereserveerd voor het besturingssysteem. Dit is het maximale geheugen dat aan SQL Server wordt toegewezen, 25 GB moet zijn. Evenzo moet voor een 64 GB-server 10 GB worden gereserveerd voor het besturingssysteem en 54 GB voor SQL Server.
We hebben allemaal wel eens gehoord of gebruikt Windows Management Instrumentation (WMI). Er zijn verschillende klassen in WMI, waarmee we informatie kunnen extraheren over de hardware, geïnstalleerde software, het besturingssysteem of zelfs het register. We kunnen zelfs instellingen wijzigen en acties uitvoeren op deze aspecten.
De klasse win32_OperatingSystem is een WMI-klasse die alle benodigde informatie bevat over de actieve besturingssysteem (voor het geval u bijvoorbeeld dual booting gebruikt). Deze klasse kan ook worden gebruikt om de hoeveelheid geheugen te krijgen die aan het besturingssysteem is toegewezen. Hier zijn enkele van de objecten die de klasse kan retourneren, die ons kunnen helpen (geheugen wordt door deze klasse gemeten in kilobytes):
- TotalVisibleMemorySize :Dit veld toont het totale fysieke geheugen dat toegankelijk is voor het besturingssysteem. Ontoegankelijke stukken geheugen kunnen ertoe leiden dat hier een kleiner dan geïnstalleerd aantal wordt weergegeven.
- FreePhysicalMemory :Dit vertelt ons hoeveel fysiek geheugen vrij is.
- TotalVirtualMemorySize :Dit is het totale virtuele geheugen dat beschikbaar is voor het besturingssysteem om te gebruiken. Dit omvat het fysieke geheugen dat op de computer is geïnstalleerd, samen met de grootte van het wisselbestand.
- FreeVirtualMemory :vergelijkbaar met FreePhysicalMemory, maar bevat ook de vrije ruimte in het paginggeheugen.
$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
We kunnen de paginabestandsinformatie ophalen met behulp van de Win32_PageFileSetting WMI-klasse.
$server='hqdbt01'
Get-WMIObject Win32_PageFileSetting -Computer $server| select @{name="ServerName";expression={$_.__Server}}, Name, InitialSize, MaximumSize
De volgende query geeft de details van het geheugengebruik op hoog niveau van de SQL-instantie.
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;
Bereid het script voor
Laten we de bovengenoemde drie uitgangen integreren in een enkele geheugenuitgang:
- SQL interne geheugenstructuren met Counter
- Beschikbaar virtueel en fysiek geheugen met WMI-object
- Instelling paginabestand met WMI
Bij de voorbereiding van HTML-inhoud draait alles om het invullen van de waarde die wordt ingevoerd vanuit de verschillende secties van het script, tussen de juiste tags.
Het script kan geldige HTML-tags bouwen. Hieronder volgen de functies die in het script worden gebruikt.
- writeHTMLHeader:deze functie wordt gebruikt om de koptekst te genereren en de stijl voor het HTML-bestand te definiëren.
- writetableFooter:dit definieert de afsluitende HTML-tags.
- writeTableHeader:dit definieert de dertien kolommen tellende uitvoerkop voor het HTML-bestand
- writeMemoryInfo:dit is de functie die het samenvoegen van de twee WMI-klasse-uitgangen uitvoert. De uitvoer van Win32_PageFileSetting, Win32_OperatingSystem en SMO SQL wordt doorgegeven als argumenten voor deze functie. De waarden kunnen in deze sectie ook verder worden getransformeerd of gemanipuleerd.
- E-mailsectie
[uitbreiden 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
[/uitbreiden]
Uitvoer
Afronden
Nu je wat nieuwe dingen hebt geleerd over geheugenbeheer van SQL Server, zul je de bronnen van SQL Server beter begrijpen.
Als er voldoende RAM op de server is, kunnen de gegevenspagina's een langere levensduur hebben in de bufferpool, wat resulteert in een drastische vermindering van de I/O-behoeften.
Hoewel databasebeheerders in de meeste gevallen vertrouwen op standaard geheugeninstellingen, moeten we begrijpen dat de interne geheugenvereisten afhankelijk zijn van de werkbelasting van de instantie.
Dit artikel is een overzicht op hoog niveau van SQL Server-geheugen en de interne onderdelen ervan. Het behandelt ook de verschillende redenen achter de prestatieknelpunten die worden veroorzaakt door het niet instellen van het maximale geheugen.
Ik heb stapsgewijze instructies toegevoegd om een geheugenrapport in te stellen en te configureren. De stappen voor het instellen van het SQL-geheugen zijn ook inbegrepen. Verder hebben we verschillende SQL-componenten besproken die bijdragen aan het gebruik van het beschikbare geheugen op de SQL Server-omgeving.
Een punt om te onthouden is dat de toewijzing en de-toewijzing van geheugen het opstarten vertraagt. Als u dus meerdere toepassingen op dezelfde server laat stoppen en starten, kan dit de prestaties beïnvloeden. Evenzo, als er meerdere andere applicaties op dezelfde server draaien, wordt het instellen van het minimum servergeheugen en het maximum servergeheugen belangrijker om optimale prestaties te garanderen.
Dat was alles voor nu...
Referenties
- Het geheugengebruik controleren
- Belang van het instellen van het maximale servergeheugen in SQL Server en hoe dit in te stellen
- Configuratieopties voor servergeheugenserver