sql >> Databasteknik >  >> RDS >> Sqlserver

Förstå vikten av minnesinställning i SQL Server

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:

  1. Förstå interna delar av SQL Server-minnesinställningar och -konfiguration
  2. SQL Server-minnet och dess inverkan på databasen och applikationsprestanda
  3. Diskutera olika SQL Server-komponenter som bidrar till minnesanvändningen
  4. Bästa metoder och rekommendationer för minnesstorlek
  5. Minnesrapport för flera servrar
  6. 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. 1 GB minne reserverat för operativsystem
  2. 1 GB vardera för varje 4 GB RAM efter de första 4 GB, upp till 16 GB RAM
  3. 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. 1 GB, minsta tilldelning
  2. + 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.
  3. + 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:

  1. SQL internminnesstrukturer med räknare
  2. Tillgängligt virtuellt och fysiskt minne med WMI-objekt
  3. 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.

  1. writeHTMLHeader:den här funktionen används för att generera Header och definiera stilen för HTML-filen.
  2. writetableFooter:detta definierar de avslutande HTML-taggarna.
  3. writeTableHeader:detta definierar den trettonkolumnerade utdatarubriken för HTML-filen
  4. 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.
  5. 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

  1. Övervaka minnesanvändning
  2. Vikten av att ställa in Max Server Memory i SQL Server och hur man ställer in det
  3. Konfigurationsalternativ för serverminne

  1. Frågeoptimering i PostgreSQL. FÖRKLARA Grunderna – Del 2

  2. MySQL-fjärranslutning misslyckas med okänd autentiseringsmetod

  3. Uppdatera flera kolumner i MERGE-satsen ORACLE

  4. Hur kan jag använda MySQL-tilldelningsoperatorn(:=) i en inbyggd fråga i viloläge?