SQLOS y Manejo de Memoria
A partir de SQL 2005 se implementa SQLOS. Podemos ver a SQLOS como una capa (Modo Usuario) por al cual SQL interacciona con el Sistema Operativo.
La necesidad de tener al SQLOS en SQL viene dada por los continuos cambios a nivel hardware y arquitectura. Windows es definido como un Sistema Operativo multipropósito, el cual permite correr y trabajar con muchas y diferentes aplicaciones, sin embargo este no es el escenario ideal para SQL. Es por esto que se introduce SQLOS, para darle a SQL cierto grado de control sobre la plataforma en la que corre. Esto lleva a que SQLOS maneje todos los sistemas de SQL de manera centralizada, permitiendo trabajar de manera más eficiente.
SQLOS tiene muchas funciones asignadas (o sistemas que maneja), estas son algunas:
- Detección de deadlocks
- Manejo de recursos
- Manejo de memoria
- Scheduler de E/S
Estructura del manejo de memoria de SQLOS:
SQLOS está compuesto por varios componentes como: nodos de memoria (memory nodes), clerks de memoria (memory clerks), caches de memoria (memory cache) y objetos de memoria (memory objects).
- Nodos de memoria: son objetos internos de SQLOS que se encargan de proveer una localización para las asignaciones (allocations) de memoria y están ocultos para cualquier otro administrador de memoria que no sea el de SQLOS. Los nodos de memoria consisten en muchos asignadores (allocators) de memoria. Uno de los asignadores de memoria más comunes es el asignador de páginas simple (Single Page Allocator), llamado así porque se encarga de asignar paginas en memoria de SQLOS en múltiplos de 8Kb, el mismo tamaño que una página de una DB en SQL.
- Clerks de memoria: al estar los nodos de memoria ocultos a otros administradores de memoria, si un cliente del administrador de memoria del SQLOS necesita hacer una asignación, lo primero que hace es crear un clerk de memoria. Cada componente de SQL tiene su propio clerk de memoria que le ayuda para proveerle memoria. Los clerks de memoria proveen métodos de asignación y estadísticas las cuales nos pueden ser útiles para hacer seguimiento y controlar la cantidad de memoria que es consumida por un componente.
- Objetos de memoria: un objeto de memoria es objeto tipo árbol y requiere de un clerk de memoria para asignar su memoria. Hay 3 tipos de objetos de memoria: objeto de memoria variable (heap común), objeto de memoria incremental (heap del tipo mark/shrink) y objeto de memoria fijo.
- Cache de memoria: es un mecanismo par cachear data heterogenea con un costo asociado a cada entrada en la chace. Usualmente cada entrada tiene un estado, el cache implementa un control de ciclo de vida de las entradas, su visibilidad y provee algún tipo de política LRU (last resource used).
Hasta acá vimos la estructura interna de SQLOS en lo que refiere a manejo de memoria.
Ahora veamos otra parte del manejo de memoria.
Buffer pool :
SQL Server organiza la memoria que el mismo se asigna en 2 regiones distintas: Buffer Pool y MemToLeave (o memoria reservada) . Si se hiciera uso de AWE, serían entonces 3 las regiones, siendo esta última el espacio de memoria asignado por AWE. El Buffer Pool es la región más destacada de las 3.
El Buffer Pool es el cache de las Bases de Datos el cual es llenado por el Buffer manager que se encarga de acceder y actualizar los datos de las páginas. Es preferible que los datos existan en el cache de memoria en vez de tener que operar con el Disco rígido ya que las operaciones de E/S pueden consumir muchos recursos y tomar un tiempo relativamente alto en terminar, es por esto que la meta es usar la mayor cantidad de memoria posible para tener una buen desempeño del cache. Para controlar la cantidad de memoria usada por el Buffer Pool se utilizan las configuraciones de memoria en SQL: max server memory y min server memory. Estas configuraciones controlan el tamaño que puede llegar a tener el Buffer pool y no la cantidad total de memoria que va a utilizar SQL Server como se cree.
Al momento de iniciar SQL server, reserva la región de MemToLeave intentando hacerlo en un rango de direcciones contiguos de VAS (Virtual Address Space) y luego el Buffer Pool decide el tamaño máximo que va a tener. Por defecto el tamaño de la región de MemtoLeave es de 384Mb, siendo 128Mb para stacks de worker threads y 256Mb para asignaciones fuera del Buffer Pool.
MemToLeave = Reserved Memory + (max worker threads * worker thread stack size) |
El tamaño del worker thread stackes de 512Kb para sistemas de 32 bits, 2Mb para sistemas de 64 bits y 4Mb para IA64; la cantidad de threads se encuentra configurado en max worker threads,en 0 por defecto en SQL 2005 y en adelante,la cantidad de worker threads dependerá del número de procesadores. Para el ejemplo usaremos 256 worker threads en un sistema de 32 bits, Entonces la cuenta queda:
MemToLeave = 256Mb + (256 * 0,5Mb) => MemToLeave = 384Mb |
Reserved Memory puede modificar su tamaño si utilizamos el parámetro de inicio –g. Si pasamos el parámetro –g512, Reserved Memory toma un tamaño de 512Mb haciendo que MemToLeave cambie de tamaño a 640Mb.
El Buffer Pool asigna páginas a medida que se solicita, dependiendo de requerimientos internos y externos. El tamaño de página de una Base de Datos es de 8Kb, por consiguiente las páginas se asignan y se quitan con tamaños de 8Kb en el Buffer Pool, coincidentemente con el mismo tamaño en que se asignan las páginas por los Nodos de memoria. En este punto es donde convergen SQLOS y el Buffer Pool, el nodo de memoria provee la localización para una página, la cual es asignada por medio de un asignador de página simple en el Buffer Pool:
Nodo de memoria ---> Asignador de página simple ---> Buffer Pool
Todos los componentes de SQL server se encuentran optimizados para asignaciones de 8Kb de memoria, de manera que pueden hacer asignaciones de memoria a través del asignador de páginas simple de SQLOS y por consiguiente a través del Buffer Pool. Sin embargo hay casos en los que se necesitan hacer asignaciones que requieren de un cache más grande, en ese caso, se van a usar otros asignadores como: asignadores de páginas múltiples (Multi-Page Allocators) y asignadores de páginas virtuales (Virtual Page Allocators), por supuesto, la memoria asignada va a estar fuera del Buffer Pool, haciéndose la asignación en la región de MemToLeave en la parte de Reserved Memory.
Cuando AWE se encuentra presente, las asignaciones se van a realizar a través de este mecanismo y no a través del asignador de páginas simple. Las API que usa AWE crean una región en el Buffer Pool en que se van a ver vistas que referencian memoria física, siendo allí donde se guardan las páginas, por ende es lógico que las asignaciones se realicen a través de AWE.
“Las opiniones e ideas expresadas en este blog son las de los Autores y no necesariamente declaran o reflejan la opinión de Microsoft”