sql >> Base de Datos >  >> RDS >> Sqlserver

Comprender la importancia de la configuración de la memoria en SQL Server

La memoria es uno de los recursos que forman el triángulo de rendimiento:la CPU y el almacenamiento son los otros dos. Si uno es golpeado, los otros dos toman la carga para tratar de llevar el rendimiento a niveles aceptables, pero siempre existe la compensación. Cualesquiera que sean las transacciones que no se puedan confirmar en la memoria, SQL Server las reenviará al subsistema de disco. Esto provoca un cuello de botella en el rendimiento. Por lo tanto, las estadísticas de espera pueden ayudar a identificar problemas de rendimiento en un servidor SQL.

En este artículo, se tratan los siguientes temas:

  1. Comprender los aspectos internos de la configuración y la configuración de la memoria de SQL Server
  2. La memoria de SQL Server y su impacto en la base de datos y el rendimiento de la aplicación
  3. Discutir varios componentes de SQL Server que contribuyen al uso de la memoria
  4. Prácticas recomendadas y recomendaciones para el tamaño de la memoria
  5. Informe de memoria multiservidor
  6. Y más...

Funciones internas de gestión de memoria

SQL Server tiene una unidad de administración de memoria que realiza una administración de memoria dinámica automatizada en función de la carga de trabajo del sistema. Esta memoria es el espacio volátil que es fundamental para las necesidades empresariales y tecnológicas de hoy en día, cuyo tamaño correcto es vital para el rendimiento óptimo de las aplicaciones.

Sin embargo, todos sabemos que al configurar el servidor, el dimensionamiento contiene algunos valores predeterminados. en algunos casos, pronto descubrimos que SQL Server usa casi toda la memoria en el servidor, aunque no hay actividad visible en las bases de datos, lo que genera preguntas:¿Son incorrectos los valores predeterminados? Si es así, ¿cuál debería ser el tamaño correcto?

La gestión de memoria en SQL Server funciona con el algoritmo de relleno y vaciado. Los valores predeterminados no restringen el crecimiento del consumo de memoria a menos que haya una solicitud del sistema operativo.

El tamaño depende de varios componentes del sistema; en muchos casos, establecerlo entre 70 % y 80 % es un buen punto de partida. Luego, también debe monitorearlo para ver qué más puede faltar y si debe modificar la configuración. Si tiene otros servicios en SQL Server (realmente no debería), es posible que deba dejar más, especialmente si estos servicios consumen mucha memoria. Considere revisar la configuración de memoria de la instancia de SQL en cualquiera de los siguientes escenarios:

  • Falta de respuesta del sistema operativo
  • Agotamiento de la aplicación
  • Operaciones de copia de seguridad que requieren grandes búferes de memoria
  • Objetos optimizados en memoria
  • Índices de almacenamiento de columnas, ya que requieren grandes volúmenes de memoria para realizar mantenimientos de índices.

La configuración de la memoria en SQL Server es bastante sencilla. Puede cambiar el valor usando sp_configure o interfaz gráfica de usuario de SSMS. Esta es una opción en línea, pero recuerde que configurar o restablecer estos valores puede causar que algunos de los objetos de la caché interna se reorganicen, lo que hará que el sistema funcione un poco más lento.

sp_configure ‘memoria máxima del servidor (MB)’,

En este caso, el número "2147483647" significa que SQL Server no tiene límite superior y utilizará toda la memoria del servidor.

Memoria mínima del servidor:memoria mínima del servidor como valor mínimo; SQL Server asignará memoria para su propio uso hasta que alcance la configuración mínima de memoria del servidor. Después de eso, mantendrá al menos esta cantidad de memoria utilizable.

Memoria máxima del servidor:de la misma manera que la memoria mínima del servidor proporciona un piso, la memoria máxima del servidor proporciona un techo.

Los niveles de memoria mínimo y máximo son el límite superior e inferior de la cantidad de memoria permitida para el uso del grupo de búfer. El grupo de búferes es la porción más grande de memoria consumida por SQL Server. Los siguientes son los componentes de SQL Server dentro de la instancia de SQL que utilizan la memoria del grupo de búfer

  • Caché de página de base de datos
  • Cachés de registros internos
  • Caché de procedimiento o caché de plan de consulta
  • Espacio de carga de trabajo de consultas
  • Bloqueos (concesiones de memoria)
  • Contexto de conexión
  • Optimización de consultas
  • Estructuras de datos a nivel del sistema

Los valores de las métricas importantes, como Mbytes disponibles, Páginas/segundo, Proporción de aciertos de caché de búfer, PLE, etc., determinan el rendimiento de SQL Server.

La proporción de aciertos de caché de búfer es específica para cada aplicación. El 90% generalmente se considera deseable. Significa que más del 90% de las solicitudes fueron atendidas por el caché, lo cual es bueno. Si el valor es más bajo, agregue más memoria hasta que sea consistentemente superior al 90 %.

Bytes disponibles no es más que una indicación de cuánta memoria está disponible para su uso. El contador de páginas/s muestra cuántas páginas se recuperaron del disco o se escribieron en el disco, ambas debido a errores de página graves.

PLE significa Expectativa de vida de la página, que es una indicación de cuántos segundos permanecerá la página en el grupo.

Por ejemplo,

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

Recomendaciones y buenas prácticas

Veamos ahora brevemente las técnicas para dimensionar la memoria.

  1. 1 GB de memoria reservado para el sistema operativo
  2. 1 GB cada uno por cada 4 GB de RAM después de los 4 GB iniciales, hasta 16 GB de RAM
  3. 1 GB cada uno por cada 8 GB en más de 16 GB de RAM

Por ejemplo, si tiene un servidor de base de datos de RAM de 32 GB, la memoria que se le dará al sistema operativo sería

  1. 1 GB, la asignación mínima
  2. + 3 GB, ya que 16 GB – 4 GB =12 GB; 12 GB divididos por 4 GB (cada 4 GB obtiene 1 GB) son 3 GB.
  3. + 2 GB, como 32 GB – 16 GB =16 GB; 16 dividido por 8 (cada 8 GB después de 16 GB obtiene 1 GB) es 2 GB

Entonces, en total, para un servidor con 32 GB de RAM, se reservarán 7 GB para el Sistema Operativo. Esta es la memoria máxima asignada a SQL Server que debe ser de 25 GB. De manera similar, para un servidor de 64 GB, se deben reservar 10 GB para el sistema operativo y se deben asignar 54 GB para SQL Server.

Todos, en algún momento u otro, hemos oído hablar o utilizado el Instrumental de administración de Windows (WMI). Hay varias clases en WMI, que nos permiten extraer información sobre el hardware, el software instalado, el sistema operativo o incluso el registro. Incluso podemos modificar configuraciones y realizar acciones sobre estos aspectos.

La clase win32_OperatingSystem es una clase WMI que tiene toda la información necesaria sobre el activo sistema operativo (en caso de que tenga, por ejemplo, arranque dual). Esta clase también se puede utilizar para obtener la cantidad de memoria asignada al sistema operativo. Estos son algunos de los objetos que la clase puede devolver, que podrían ser de ayuda para nosotros (esta clase mide la memoria en kilobytes):

  • Tamaño total de memoria visible :este campo muestra la memoria física total a la que puede acceder el sistema operativo. Los fragmentos de memoria inaccesibles pueden hacer que se muestre aquí un número menor que el instalado.
  • Memoria Física Gratuita :Esto nos dice qué cantidad de memoria física está libre.
  • Tamaño total de la memoria virtual :Esta es la memoria virtual total disponible para que la use el sistema operativo. Esto comprende la memoria física instalada en la computadora, junto con el tamaño del archivo de paginación.
  • Memoria virtual gratuita :Similar a FreePhysicalMemory, pero también incluye el espacio libre en la memoria de paginación.
$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 

Podemos obtener la información del archivo de la página usando la clase WMI Win32_PageFileSetting.

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

La siguiente consulta proporciona los detalles de uso de memoria de alto nivel de la instancia de 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;

Preparar el guión

Integremos las tres salidas antes mencionadas en una sola salida de memoria:

  1. Estructuras de memoria interna de SQL usando Counter
  2. Memoria virtual y física disponible mediante el objeto WMI
  3. Configuración del archivo de página mediante WMI

La preparación del contenido HTML consiste en completar el valor alimentado desde las diferentes secciones del script, entre las etiquetas correctas.

El script puede crear etiquetas HTML válidas. Las siguientes son las funciones utilizadas en el script.

  1. writeHTMLHeader:esta función se utiliza para generar el encabezado y definir el estilo del archivo HTML.
  2. writetableFooter:esto define las etiquetas HTML de cierre.
  3. writeTableHeader:esto define el encabezado de salida de trece columnas para el archivo HTML
  4. writeMemoryInfo:esta es la función que realiza la fusión de las dos salidas de la clase WMI. La salida de Win32_PageFileSetting, Win32_OperatingSystem y SMO SQL se pasa como argumentos para esta función. Los valores también se pueden transformar o manipular aún más en esta sección.
  5. Sección de correo electrónico

[expandir título=”Código”]

# 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
 

[/expandir]

Salida

Conclusión

Ahora que ha aprendido algunas cosas nuevas sobre la administración de memoria de SQL Server, comprenderá mejor los recursos de SQL Server.

Si hay suficiente RAM en el servidor, las páginas de datos pueden tener una vida útil más larga en el grupo de búfer, lo que en consecuencia da como resultado una reducción drástica de las necesidades de E/S.

Si bien en la mayoría de los casos, los administradores de bases de datos confían en la configuración de memoria predeterminada, debemos comprender que los requisitos internos de memoria dependen de la carga de trabajo de la instancia.

Este artículo es un tutorial de alto nivel de la memoria de SQL Server y sus componentes internos. Además, cubre las diversas razones detrás de los cuellos de botella de rendimiento causados ​​por no configurar la memoria máxima.

He incluido instrucciones paso a paso para instalar y configurar un informe de memoria. También se incluyen los pasos sobre cómo configurar la memoria SQL. Además, analizamos varios componentes de SQL que contribuyen al uso de la memoria disponible en el entorno de SQL Server.

Un punto a recordar es que la asignación y la desasignación de memoria ralentizan el inicio. Por lo tanto, si tiene varias aplicaciones que se detienen y se inician en el mismo servidor, puede afectar el rendimiento. Del mismo modo, si hay varias otras aplicaciones ejecutándose en el mismo servidor, configurar la memoria mínima del servidor y la memoria máxima del servidor se vuelve más importante para garantizar un rendimiento óptimo.

Eso es todo por ahora...

Referencias

  1. Supervisión del uso de la memoria
  2. Importancia de configurar Max Server Memory en SQL Server y cómo configurarlo
  3. Opciones de configuración del servidor de memoria del servidor