Minne är en av resurserna som bildar prestandatriangeln – CPU och lagring är de andra två. Om en träffas tar de andra två lasset för att försöka få prestandan till acceptabla nivåer, men det finns alltid en avvägning. Vilka transaktioner som än inte kan överföras till minnet skulle de vidarebefordras till diskundersystemet av SQL Server. Detta orsakar en prestandaflaskhals. Därför kan väntestatistiken hjälpa till att identifiera prestandaproblem på en SQL Server.
I den här artikeln diskuteras följande ämnen:
- Förstå interna delar av SQL Server-minnesinställningar och -konfiguration
- SQL Server-minnet och dess inverkan på databasen och applikationsprestanda
- Diskutera olika SQL Server-komponenter som bidrar till minnesanvändningen
- Bästa metoder och rekommendationer för minnesstorlek
- Minnesrapport för flera servrar
- Och mer...
Interna funktioner för minneshantering
SQL Server har en minneshanteringsenhet som utför automatiserad dynamisk minneshantering baserat på systemets arbetsbelastning. Detta minne är det flyktiga utrymmet som är avgörande för dagens affärsbehov – tekniska behov, vars rätt storlek är avgörande för applikationernas optimala prestanda.
Men vi vet alla att när du ställer in servern innehåller storleken några standardvärden. i vissa fall får vi snart reda på att SQL Server använder nästan allt minne på servern, även om det inte finns någon synlig aktivitet på databaserna, vilket leder till frågorna:Är standardvärdena felaktiga? Om så är fallet, vad ska vara rätt storlek?
Minneshantering på SQL Server fungerar på Fill-and-Flush-algoritmen. Standardvärdena begränsar inte minnesförbrukningen från att växa om det inte finns en begäran från operativsystemet.
Storleken beror på olika komponenter i systemet – i många fall är det en bra utgångspunkt att ställa in den mellan 70 % och 80 %. Sedan bör du också övervaka den för att se vad mer du kan sakna och om du bör justera inställningen. Om du har andra tjänster på SQL Server (du borde verkligen inte) kan du behöva lämna efter dig fler, speciellt om dessa tjänster är minnessvin. Överväg att återgå till minnesinställningen för SQL-instansen i något av följande scenarier:
- Inte svarar hos operativsystemet
- Programutmattning
- Säkerhetskopiering som kräver stora minnesbuffertar
- In-Memory-optimerade objekt
- Kolumnlagringsindex, eftersom de kräver stora volymer minne för att utföra indexunderhåll.
Minnesinställningen på SQL Server är ganska enkel. Du kan ändra värdet med sp_configure eller SSMS GUI. Detta är ett onlinealternativ, men kom ihåg att inställning eller återställning av dessa värden kan göra att vissa av de interna cacheobjekten blandas om, vilket gör att systemet går något långsammare.
sp_configure 'max serverminne (MB)',
I det här fallet betyder siffran "2147483647" att SQL Server inte har någon övre gräns och kommer att använda allt minne på servern.
Min serverminne:min serverminne som golvvärde; SQL Server kommer att överföra minne för eget bruk tills den når min serverminnesinställning. Efter det kommer den att behålla åtminstone denna mängd användbart minne.
Max serverminne:På samma sätt som min serverminne ger ett golv, ger max serverminne ett tak.
Min och max minnesnivåer är den nedre och övre gränsen för mängden minne som tillåts för användning av buffertpoolen. Buffertpoolen är den största minnesbiten som förbrukas av SQL Server. Följande är SQL Server-komponenterna i SQL-instansen som använder minne från buffertpoolen
- Databassidecache
- Interna loggcacher
- Procedurcache eller frågeplanscache
- Fråga arbetsbelastningsutrymme
- Lås (minnesbidrag)
- Anslutningskontext
- Optimera frågor
- Datastrukturer på systemnivå
Värdena för de viktiga mätvärdena som Tillgängliga Mbyte, Sidor/Sek, Buffer Cache Hit Ratio, PLE, etc. bestämmer SQL Server-prestanda.
Buffer Cache Hit Ratio är specifik för varje applikation. 90 % brukar anses vara önskvärt. Det betyder att över 90 % av förfrågningarna serverades av cachen, vilket är bra. Om värdet är lägre, lägg till mer minne tills det konstant är högre än 90 %.
Tillgängliga bytes är inget annat än en indikation på hur mycket minne som är tillgängligt för användning. Räknaren Sidor/sek visar hur många sidor som hämtades från disken eller skrevs till disken, båda på grund av fel på hårdsidan.
PLE står för Page Life Expectancy, vilket är en indikation på hur många sekunder sidan kommer att stanna i poolen.
Till exempel,
$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
}
Rekommendationer och bästa metoder
Låt oss nu kort titta på teknikerna för att dimensionera minnet.
- 1 GB minne reserverat för operativsystem
- 1 GB vardera för varje 4 GB RAM efter de första 4 GB, upp till 16 GB RAM
- 1 GB vardera för varje 8 GB i mer än 16 GB RAM
Till exempel, om du har en 32 GB RAM-databasserver, så är minne som ska ges till operativsystemet
- 1 GB, minsta tilldelning
- + 3 GB, eftersom 16 GB – 4 GB =12 GB; 12 GB delat med 4 GB (varje 4 GB får 1 GB) är 3 GB.
- + 2 GB, som 32 GB – 16 GB =16 GB; 16 dividerat med 8 (varje 8 GB efter 16 GB får 1 GB) är 2 GB
Så totalt, för en server med 32 GB RAM, kommer 7 GB att reserveras för operativsystemet. Detta är det maximala minne som tilldelas SQL Server bör vara 25 GB. På samma sätt, för en 64 GB-server, bör 10 GB reserveras för operativsystemet och 54 GB bör tilldelas för SQL Server.
Vi har alla, någon gång, hört talas om eller använt Windows Management Instrumentation (WMI). Det finns flera klasser i WMI, som gör att vi kan extrahera information om hårdvaran, installerad programvara, operativsystemet eller till och med registret. Vi kan till och med ändra inställningar och utföra åtgärder på dessa aspekter.
Klassen win32_OperatingSystem är en WMI-klass som har all nödvändig information om den aktiva operativsystem (om du, säg, dubbelstartar). Denna klass kan också användas för att få mängden minne som allokerats till operativsystemet. Här är några av objekten som klassen kan returnera, vilket kan vara till hjälp för oss (minnet mäts i kilobyte av denna klass):
- TotalVisibleMemorySize :Detta fält visar det totala fysiska minnet som är tillgängligt för operativsystemet. Otillgängliga minnesbitar kan göra att ett mindre antal än installerat visas här.
- FreePhysicalMemory :Detta talar om för oss hur mycket fysiskt minne som är ledigt.
- TotalVirtualMemorySize :Detta är det totala virtuella minnet som är tillgängligt för operativsystemet att använda. Detta omfattar det fysiska minnet som är installerat på datorn, tillsammans med storleken på sidfilen.
- FreeVirtualMemory :Liknar FreePhysicalMemory, men inkluderar även det lediga utrymmet i personsökningsminnet.
$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
Vi kan hämta sidfilinformationen med Win32_PageFileSetting WMI-klassen.
$server='hqdbt01'
Get-WMIObject Win32_PageFileSetting -Computer $server| select @{name="ServerName";expression={$_.__Server}}, Name, InitialSize, MaximumSize
Följande fråga ger information om minnesanvändning på hög nivå för SQL-instansen.
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;
Förbered skriptet
Låt oss integrera de tre ovannämnda utgångarna i en enda minnesutgång:
- SQL internminnesstrukturer med räknare
- Tillgängligt virtuellt och fysiskt minne med WMI-objekt
- Sidfilsinställning med WMI
HTML-innehållsförberedelsen handlar om att fylla i värdet som matas in från de olika avsnitten av skriptet, mellan rätt taggar.
Skriptet kan bygga giltiga HTML-taggar. Följande är funktionerna som används i skriptet.
- writeHTMLHeader:den här funktionen används för att generera Header och definiera stilen för HTML-filen.
- writetableFooter:detta definierar de avslutande HTML-taggarna.
- writeTableHeader:detta definierar den trettonkolumnerade utdatarubriken för HTML-filen
- writeMemoryInfo:detta är funktionen som utför sammanslagning av de två WMI-klassutgångarna. Utdata från Win32_PageFileSetting, Win32_OperatingSystem och SMO SQL skickas som argument för denna funktion. Värdena kan också transformeras eller manipuleras ytterligare i det här avsnittet.
- E-postavsnitt
[expand title="Kod"]
# 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
[/expand]
Utdata
Avsluta
Nu när du har lärt dig några nya saker om SQL Server-minneshantering kommer du att bättre förstå SQL Server-resurser.
Om det finns tillräckligt med RAM-minne på servern kan datasidorna få en längre livslängd i buffertpoolen, vilket resulterar i en drastisk minskning av I/O-behovet.
Även om databasadministratörer i de flesta fall förlitar sig på standardminnesinställningar, måste vi förstå att kraven på internminnet beror på instansens arbetsbelastning.
Den här artikeln är en genomgång av SQL Server-minne och dess interna funktioner på hög nivå. Den täcker också de olika orsakerna bakom prestandaflaskhalsarna som orsakas av att inte ställa in maxminnet.
Jag har inkluderat steg-för-steg-instruktioner för att ställa in och konfigurera en minnesrapport. Stegen för hur du ställer in SQL-minnet ingår också. Vidare diskuterade vi olika SQL-komponenter som bidrar till användningen av det tillgängliga minnet i SQL Server-miljön.
En punkt att komma ihåg är att tilldelning och avallokering av minne saktar ner uppstarten. Därför, om du har flera applikationer som stoppar och startar på samma server, kan det påverka prestandan. På liknande sätt, om det finns flera andra applikationer som körs på samma server, blir det viktigare att ställa in min serverminne och max serverminne för att säkerställa optimal prestanda.
Det var allt för nu...
Referenser
- Övervaka minnesanvändning
- Vikten av att ställa in Max Server Memory i SQL Server och hur man ställer in det
- Konfigurationsalternativ för serverminne