sql >> Databáze >  >> RDS >> Sqlserver

Pochopení důležitosti nastavení paměti v SQL Server

Paměť je jedním ze zdrojů tvořících výkonnostní trojúhelník – CPU a úložiště jsou další dva. Pokud je zasažen jeden, další dva převezmou zátěž, aby se pokusily dostat výkon na přijatelnou úroveň, ale vždy existuje kompromis. Bez ohledu na transakce, které nelze potvrdit do paměti, budou SQL Serverem předány diskovému subsystému. To způsobuje problémové místo výkonu. Statistiky čekání proto mohou pomoci identifikovat problémy s výkonem na serveru SQL.

V tomto článku jsou popsána následující témata:

  1. Porozumění vnitřním prvkům nastavení a konfigurace paměti SQL Server
  2. Paměť serveru SQL a její dopad na výkon databáze a aplikace
  3. Prodiskutujte různé součásti serveru SQL Server, které přispívají k využití paměti
  4. Osvědčené postupy a doporučení pro velikost paměti
  5. Hlášení o paměti více serverů
  6. A další…

Interní správa paměti

SQL Server má jednotku správy paměti, která provádí automatizovanou dynamickou správu paměti na základě pracovní zátěže systému. Tato paměť je nestálý prostor, který je kritický pro dnešní potřeby Business – Tech, jehož správná velikost je zásadní pro optimální výkon aplikací.

Všichni však víme, že při nastavování serveru velikost obsahuje některé výchozí hodnoty. v některých případech brzy zjistíme, že SQL Server využívá téměř veškerou paměť na serveru, i když v databázích není žádná viditelná aktivita, což přináší otázky:Jsou výchozí hodnoty nesprávné? Pokud ano, jaká by měla být správná velikost?

Správa paměti na serveru SQL Server funguje na algoritmu Fill-and-Flush. Výchozí hodnoty neomezují nárůst spotřeby paměti, pokud neexistuje požadavek operačního systému.

Velikost závisí na různých komponentách systému – v mnoha případech je dobrým výchozím bodem nastavení mezi 70 % a 80 %. Poté byste jej měli také sledovat, abyste viděli, co vám ještě může chybět a zda byste neměli nastavení vyladit. Pokud máte na SQL Serveru další služby (opravdu byste neměli), možná budete muset zanechat více, zvláště pokud jsou tyto služby paměťovými prasaty. Zvažte přehodnocení nastavení paměti instance SQL v kterémkoli z následujících scénářů:

  • Nereaguje operační systém
  • Vyčerpání aplikace
  • Operace zálohování, které vyžadují velké vyrovnávací paměti
  • Objekty optimalizované v paměti
  • Sloupcové ukládat indexy, protože vyžadují velké objemy paměti k provádění údržby indexů.

Nastavení paměti na SQL Server je docela jednoduché. Hodnotu můžete změnit pomocí sp_configure nebo SSMS GUI. Toto je online možnost, ale pamatujte, že nastavení nebo resetování těchto hodnot může způsobit přeskupení některých objektů vnitřní mezipaměti, což způsobí, že systém poběží o něco pomaleji.

sp_configure ‘maximální paměť serveru (MB)’,

V tomto případě číslo „2147483647“ znamená, že SQL Server nemá žádný horní limit a využije veškerou paměť na serveru.

Minimální paměť serveru:minimální paměť serveru jako minimální hodnota; SQL Server potvrdí paměť pro své vlastní použití, dokud nedosáhne nastavení minimální paměti serveru. Poté bude udržovat alespoň toto množství použitelné paměti.

Max. paměť serveru:Stejně jako minimální paměť serveru poskytuje spodní hranici, maximální paměť serveru poskytuje strop.

Minimální a maximální úrovně paměti jsou spodní a horní limit množství paměti povolené pro použití ve společné oblasti vyrovnávacích pamětí. Fond vyrovnávacích pamětí je největší část paměti spotřebovaná SQL Serverem. Následují součásti SQL Server v rámci instance SQL, které využívají paměť z fondu vyrovnávacích pamětí

  • Mezipaměť databázových stránek
  • Interní mezipaměti protokolů
  • Mezipaměť procedur nebo plán dotazů
  • Dotazový pracovní prostor
  • Zámky (udělení paměti)
  • Kontext připojení
  • Optimalizace dotazů
  • Datové struktury na úrovni systému

Hodnoty důležitých metrik, jako jsou dostupné bajty, stránky/s, poměr zásahů do mezipaměti vyrovnávací paměti, PLE atd., určují výkon serveru SQL.

Poměr návštěvnosti mezipaměti je specifický pro každou aplikaci. 90 % se obvykle považuje za žádoucí. To znamená, že více než 90 % požadavků bylo obsluhováno mezipamětí, což je dobrá věc. Pokud je hodnota nižší, přidejte více paměti, dokud nebude trvale vyšší než 90 %.

Dostupné bajty nejsou nic jiného než údaj o tom, kolik paměti je k dispozici pro použití. Počítadlo stránek/s ukazuje, kolik stránek bylo načteno z disku nebo zapsáno na disk, obojí kvůli chybám pevných stránek.

PLE znamená očekávanou životnost stránky, což je údaj o tom, kolik sekund stránka zůstane ve fondu.

Například,

$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
   }

Doporučení a osvědčené postupy

Podívejme se nyní krátce na techniky velikosti paměti.

  1. 1 GB paměti vyhrazené pro operační systém
  2. 1 GB každý na každé 4 GB RAM po počátečních 4 GB, až 16 GB RAM
  3. 1 GB každý na každých 8 GB ve více než 16 GB paměti RAM

Pokud máte například databázový server s kapacitou 32 GB RAM, paměť, která má být přidělena operačnímu systému, by byla

  1. 1 GB, minimální přidělení
  2. + 3 GB, od 16 GB – 4 GB =12 GB; 12 GB děleno 4 GB (každé 4 GB dostane 1 GB) jsou 3 GB.
  3. + 2 GB, jako 32 GB – 16 GB =16 GB; 16 děleno 8 (každých 8 GB po 16 GB získá 1 GB) je 2 GB

Celkem tedy pro server s 32 GB RAM bude pro operační systém vyhrazeno 7 GB. Toto je maximální paměť přidělená serveru SQL Server by měla být 25 GB. Podobně pro 64GB server by mělo být 10 GB vyhrazeno pro operační systém a 54 GB by mělo být přiděleno pro SQL Server.

Všichni jsme v určitém okamžiku slyšeli nebo používali Windows Management Instrumentation (WMI). Ve WMI existuje několik tříd, které nám umožňují extrahovat informace o hardwaru, nainstalovaném softwaru, operačním systému nebo dokonce o registru. Můžeme dokonce upravit nastavení a provádět akce s těmito aspekty.

Třída win32_OperatingSystem je třída WMI, která má všechny potřebné informace o aktivním operační systém (v případě, že používáte, řekněme, duální bootování). Tuto třídu lze také použít k získání množství paměti přidělené operačnímu systému. Zde jsou některé z objektů, které může třída vrátit, což by nám mohlo pomoci (paměť se u této třídy měří v kilobajtech):

  • TotalVisibleMemorySize :Toto pole zobrazuje celkovou fyzickou paměť, která je přístupná operačnímu systému. Nepřístupné části paměti mohou způsobit, že se zde zobrazí číslo menší, než je nainstalované.
  • FreePhysicalMemory :To nám říká, jaké množství fyzické paměti je volné.
  • TotalVirtualMemorySize :Toto je celková virtuální paměť dostupná pro operační systém. To zahrnuje fyzickou paměť nainstalovanou v počítači spolu s velikostí stránkovacího souboru.
  • FreeVirtualMemory :Podobné jako FreePhysicalMemory, ale zahrnuje také volné místo ve stránkovací paměti.
$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 

Informace o souboru stránky můžeme načíst pomocí třídy WMI Win32_PageFileSetting.

$server='hqdbt01'
Get-WMIObject Win32_PageFileSetting -Computer $server|  select @{name="ServerName";expression={$_.__Server}}, Name, InitialSize, MaximumSize 

Následující dotaz poskytuje podrobnosti o využití paměti na vysoké úrovni instance 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;

Připravte skript

Pojďme integrovat výše uvedené tři výstupy do jediného paměťového výstupu:

  1. Struktury interní paměti SQL pomocí čítače
  2. Dostupná virtuální a fyzická paměť pomocí objektu WMI
  3. Nastavení souboru stránky pomocí WMI

Příprava obsahu HTML je o vyplnění hodnoty přiváděné z jiné části skriptu mezi správné značky.

Skript může vytvářet platné značky HTML. Následují funkce použité ve skriptu.

  1. writeHTMLHeader:tato funkce se používá ke generování záhlaví a definování stylu pro soubor HTML.
  2. writetableFooter:definuje uzavírací značky HTML.
  3. writeTableHeader:definuje výstupní záhlaví souboru HTML ve třinácti sloupcích
  4. writeMemoryInfo:toto je funkce, která provádí sloučení dvou výstupů třídy WMI. Výstup Win32_PageFileSetting, Win32_OperatingSystem a SMO SQL je předán jako argumenty pro tuto funkci. V této sekci lze také hodnoty dále transformovat nebo s nimi manipulovat.
  5. E-mailová sekce

[expand title=”Kód”]

# 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]

Výstup

Zabalení

Nyní, když jste se naučili nějaké nové věci o správě paměti SQL Server, budete lépe rozumět zdrojům SQL Server.

Pokud je na serveru dostatečná paměť RAM, datové stránky mohou mít delší životnost ve fondu vyrovnávací paměti, což následně vede k drastickému snížení potřeb I/O.

Zatímco ve většině případů správci databáze spoléhají na výchozí nastavení paměti, musíme pochopit, že vnitřní požadavky na paměť závisí na pracovní zátěži instance.

Tento článek je podrobným průvodcem paměti SQL Server a jeho vnitřních částí. Také pokrývá různé důvody, které stojí za omezením výkonu způsobeným nenastavováním maximální paměti.

Zahrnul jsem podrobné pokyny k nastavení a konfiguraci zprávy o paměti. Zahrnuty jsou také kroky, jak nastavit paměť SQL. Dále jsme diskutovali o různých komponentách SQL, které přispívají k využití dostupné paměti v prostředí SQL Server.

Jeden bod, který je třeba si zapamatovat, je, že alokace a zrušení přidělení paměti zpomaluje spouštění. Pokud se tedy na stejném serveru zastavuje a spouští několik aplikací, může to ovlivnit výkon. Podobně, pokud na stejném serveru běží několik dalších aplikací, je pro zajištění optimálního výkonu důležitější nastavení minimální paměti serveru a maximální paměti serveru.

To je prozatím vše…

Odkazy

  1. Monitorování využití paměti
  2. Význam nastavení maximální paměti serveru v SQL Server a jak ji nastavit
  3. Možnosti konfigurace serveru paměti serveru

  1. Jak MAKE_SET() funguje v MariaDB

  2. Rozlišují se v názvech sloupců PostgreSQL velká a malá písmena?

  3. Jak vybrat vnořený JSON v SQL Server s OPENJSON

  4. Kopírování řádku ve stejné tabulce, aniž byste museli zadávat více než 50 názvů sloupců (při změně 2 sloupců)