Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Comprendere l'importanza dell'impostazione della memoria in SQL Server

La memoria è una delle risorse che formano il triangolo delle prestazioni:CPU e storage sono le altre due. Se uno viene colpito, gli altri due prendono il carico per cercare di portare le prestazioni a livelli accettabili, ma c'è sempre il compromesso. Qualunque transazione non possa essere impegnata nella memoria, verrebbe inoltrata al sottosistema del disco da SQL Server. Ciò provoca un collo di bottiglia delle prestazioni. Pertanto, le statistiche di attesa possono aiutare a identificare i problemi di prestazioni su un server SQL.

In questo articolo vengono discussi i seguenti argomenti:

  1. Comprensione degli elementi interni dell'impostazione e configurazione della memoria di SQL Server
  2. La memoria di SQL Server e il suo impatto sulle prestazioni del database e delle applicazioni
  3. Discutere vari componenti di SQL Server che contribuiscono all'utilizzo della memoria
  4. Best practice e consigli per il dimensionamento della memoria
  5. Rapporto memoria multi-server
  6. E altro ancora...

Interni di gestione della memoria

SQL Server dispone di un'unità di gestione della memoria che esegue la gestione dinamica della memoria automatizzata in base al carico di lavoro del sistema. Questa memoria è lo spazio volatile fondamentale per le odierne esigenze aziendali e tecnologiche, il cui dimensionamento corretto è vitale per le prestazioni ottimali delle applicazioni.

Tuttavia, sappiamo tutti che durante la configurazione del server, il dimensionamento contiene alcuni valori predefiniti. in alcuni casi, scopriamo presto che SQL Server utilizza quasi tutta la memoria sul server, anche se non c'è attività visibile sui database, ponendo le domande:i valori predefiniti sono errati? Se sì, quale dovrebbe essere la taglia giusta?

Gestione della memoria su SQL Server funziona sull'algoritmo Fill-and-Flush. I valori predefiniti non limitano l'aumento del consumo di memoria a meno che non vi sia una richiesta dal sistema operativo.

Il dimensionamento dipende da vari componenti del sistema:in molti casi, impostarlo tra il 70% e l'80% è un buon punto di partenza. Quindi, dovresti anche monitorarlo per vedere cos'altro potresti perderti e se dovresti modificare l'impostazione. Se disponi di altri servizi su SQL Server (in realtà non dovresti), potrebbe essere necessario lasciarne di più, soprattutto se questi servizi sono divoratori di memoria. Prendi in considerazione la possibilità di rivedere l'impostazione della memoria dell'istanza SQL in uno dei seguenti scenari:

  • Mancata risposta del sistema operativo
  • Applicazione in esaurimento
  • Operazioni di backup che richiedono grandi buffer di memoria
  • Oggetti ottimizzati in memoria
  • Indici dell'archivio colonne, poiché richiedono grandi volumi di memoria per eseguire la manutenzione degli indici.

L'impostazione della memoria su SQL Server è piuttosto semplice. Puoi modificare il valore utilizzando sp_configure o GUI SSMS. Questa è un'opzione online, ma ricorda che l'impostazione o il ripristino di questi valori può causare il rimpasto di alcuni oggetti della cache interna, che lascerà il sistema a funzionare leggermente più lentamente.

sp_configure 'memoria massima del server (MB)',

In questo caso, il numero "2147483647" significa che SQL Server non ha un limite superiore e utilizzerà tutta la memoria del server.

Memoria minima del server:memoria minima del server come valore di base; SQL Server eseguirà il commit della memoria per uso proprio finché non raggiunge l'impostazione di memoria minima del server. Dopodiché, manterrà almeno questa quantità di memoria utilizzabile.

Memoria massima del server:allo stesso modo in cui la memoria minima del server fornisce un livello minimo, la memoria massima del server fornisce un limite.

I livelli di memoria minimo e massimo sono il limite inferiore e superiore della quantità di memoria consentita per l'utilizzo da parte del pool di buffer. Il pool di buffer è il blocco di memoria più grande consumato da SQL Server. Di seguito sono riportati i componenti di SQL Server all'interno dell'istanza SQL che utilizzano la memoria del pool di buffer

  • Cache della pagina del database
  • Cache di registro interne
  • Cache di procedura o cache del piano di query
  • Interroga spazio di carico di lavoro
  • Blocchi (concessioni di memoria)
  • Contesto di connessione
  • Ottimizzazione delle query
  • Strutture di dati a livello di sistema

I valori delle metriche importanti come Mbyte disponibili, Pagine/Sec, Buffer Cache Hit Ratio, PLE e così via determinano le prestazioni di SQL Server.

Buffer Cache Hit Ratio è specifico per ciascuna applicazione. Il 90% è generalmente considerato desiderabile. Significa che oltre il 90% delle richieste è stato servito dalla cache, il che è positivo. Se il valore è inferiore, aggiungi più memoria finché non è costantemente superiore al 90%.

I byte disponibili non sono altro che un'indicazione di quanta memoria è disponibile per l'uso. Il contatore Pagine/sec mostra quante pagine sono state recuperate dal disco o scritte sul disco, entrambi a causa di errori di pagina hardware.

PLE sta per Page Life Expectancy, che indica per quanti secondi la pagina rimarrà nel pool.

Ad esempio,

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

Raccomandazioni e best practice

Vediamo ora brevemente le tecniche per dimensionare la memoria.

  1. 1 GB di memoria riservata al Sistema Operativo
  2. 1 GB ciascuno per ogni 4 GB di RAM dopo i 4 GB iniziali, fino a 16 GB di RAM
  3. 1 GB ciascuno ogni 8 GB in più di 16 GB di RAM

Ad esempio, se si dispone di un server database da 32 GB di RAM, la memoria da assegnare al sistema operativo sarebbe

  1. 1 GB, l'allocazione minima
  2. + 3 GB, poiché 16 GB – 4 GB =12 GB; 12 GB divisi per 4 GB (ogni 4 GB ottiene 1 GB) sono 3 GB.
  3. + 2 GB, come 32 GB – 16 GB =16 GB; 16 diviso per 8 (ogni 8 GB dopo 16 GB ottiene 1 GB) è 2 GB

Quindi, in totale, per un server con 32 GB di RAM, 7 GB saranno riservati al Sistema Operativo. Questa è la memoria massima allocata a SQL Server dovrebbe essere 25 GB. Allo stesso modo, per un server da 64 GB, 10 GB dovrebbero essere riservati per il sistema operativo e 54 GB dovrebbero essere allocati per SQL Server.

Tutti, prima o poi, abbiamo sentito parlare o utilizzato Strumentazione gestione Windows (WMI). Esistono diverse classi in WMI, che ci consentono di estrarre informazioni sull'hardware, sul software installato, sul sistema operativo o persino sul registro. Possiamo persino modificare le impostazioni ed eseguire azioni su questi aspetti.

La classe win32_OperatingSystem è una classe WMI che ha tutte le informazioni necessarie sull'attivo sistema operativo (nel caso in cui tu sia, diciamo, dual boot). Questa classe può essere utilizzata anche per ottenere la quantità di memoria allocata al sistema operativo. Ecco alcuni degli oggetti che la classe può restituire, che potrebbero esserci di aiuto (la memoria è misurata in kilobyte da questa classe):

  • TotalVisibleMemorySize :questo campo mostra la memoria fisica totale accessibile al sistema operativo. Blocchi di memoria inaccessibili possono causare la visualizzazione di un numero inferiore a quello installato.
  • Memoria fisica gratuita :Questo ci dice quale quantità di memoria fisica è libera.
  • TotalVirtualMemorySize :questa è la memoria virtuale totale disponibile per il sistema operativo da utilizzare. Ciò comprende la memoria fisica installata sul computer, insieme alla dimensione del file di paging.
  • Memoria virtuale gratuita :simile a FreePhysicalMemory, ma include anche lo spazio libero nella memoria di paging.
$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 

Possiamo recuperare le informazioni sul file di paging utilizzando la classe WMI Win32_PageFileSetting.

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

La query seguente fornisce i dettagli sull'utilizzo della memoria di alto livello dell'istanza 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;

Prepara lo script

Integriamo i suddetti tre output in un unico output di memoria:

  1. Strutture di memoria interna SQL che utilizzano Counter
  2. Memoria virtuale e fisica disponibile utilizzando l'oggetto WMI
  3. Impostazione del file di pagina tramite WMI

La preparazione del contenuto HTML consiste nel compilare il valore fornito dalla diversa sezione dello script, tra i tag giusti.

Lo script può creare tag HTML validi. Le seguenti sono le funzioni utilizzate nello script.

  1. writeHTMLHeader:questa funzione serve per generare l'Header e definire lo stile per il file HTML.
  2. writetableFooter:definisce i tag HTML di chiusura.
  3. writeTableHeader:definisce l'intestazione di output a tredici colonne per il file HTML
  4. writeMemoryInfo:è la funzione che esegue l'unione delle due uscite della classe WMI. L'output di Win32_PageFileSetting, Win32_OperatingSystem e SMO SQL viene passato come argomenti per questa funzione. I valori possono anche essere ulteriormente trasformati o manipolati in questa sezione.
  5. Sezione e-mail

[expand title=”Codice”]

# 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
 

[/espandi]

Uscita

Conclusione

Ora che hai appreso alcune cose nuove sulla gestione della memoria di SQL Server, capirai meglio le risorse di SQL Server.

Se sul server è presente una RAM adeguata, le pagine di dati possono avere una vita più lunga nel pool di buffer che di conseguenza si traduce in una drastica riduzione delle esigenze di I/O.

Sebbene nella maggior parte dei casi gli amministratori di database si basino sulle impostazioni di memoria predefinite, è necessario comprendere che i requisiti interni della memoria dipendono dal carico di lavoro dell'istanza.

Questo articolo è una procedura dettagliata di alto livello della memoria di SQL Server e dei relativi componenti interni. Inoltre, copre i vari motivi alla base dei colli di bottiglia delle prestazioni causati dalla mancata impostazione della memoria massima.

Ho incluso istruzioni dettagliate per impostare e configurare un rapporto di memoria. Sono inclusi anche i passaggi su come impostare la memoria SQL. Inoltre, abbiamo discusso di vari componenti SQL che contribuiscono all'utilizzo della memoria disponibile nell'ambiente SQL Server.

Un punto da ricordare è che l'allocazione e la delocalizzazione della memoria rallentano l'avvio. Pertanto, se diverse applicazioni vengono arrestate e avviate sullo stesso server, ciò potrebbe influire sulle prestazioni. Allo stesso modo, se ci sono molte altre applicazioni in esecuzione sullo stesso server, l'impostazione della memoria minima del server e della memoria massima del server diventa più importante per garantire prestazioni ottimali.

Per ora è tutto...

Riferimenti

  1. Monitoraggio dell'utilizzo della memoria
  2. Importanza dell'impostazione della memoria massima del server in SQL Server e come impostarla
  3. Opzioni di configurazione del server di memoria del server