Consumo de memoria en SQL Server usando GeneXus.

Migrando a GeneXus Ev2 Upgrade 5, necesite hacer REBUILD ALL de algunas KB grandes. (10.000 objetos generables).
Esto me hizo recordar cuan lento se pone la maquina de desarrollo mientras ejecuta dicho REBUILD ALL.

Analizando un poco el problema, lo que veo que lo que mas enlentece mi notebook es el consumo de memoria de SQL Server, pues el CPU está sobradisimo. (menos de 20% de uso)

Mi notebook tiene 8GB de memoria y SQLServer está usando mas de 3Gb.

Me puse a investigar superficialmente como saber en que se usa la memoria dentro de SQL Server y encontre este script para hacerlo (no recuerdo la fuente :(  )

Los dejo aca, para que me sea mas facil encontrarlos la proxima vez que los necesite.

--find out how big buffer pool is and determine percentage used by each database

DECLARE @total_buffer INT;
SELECT @total_buffer = cntr_value   FROM sys.dm_os_performance_counters
WHERE RTRIM([object_name]) LIKE '%Buffer Manager'   AND counter_name = 'Total Pages';
;WITH src AS(   SELECT        database_id, db_buffer_pages = COUNT_BIG(*)
FROM sys.dm_os_buffer_descriptors       --WHERE database_id BETWEEN 5 AND 32766      
GROUP BY database_id)SELECT   [db_name] = CASE [database_id] WHEN 32767        THEN 'Resource DB'        ELSE DB_NAME([database_id]) END,   db_buffer_pages,   db_buffer_MB = db_buffer_pages / 128,   db_buffer_percent = CONVERT(DECIMAL(6,3),db_buffer_pages * 100.0 / @total_buffer)
FROM src
ORDER BY db_buffer_MB DESC;
Una vez que veo cuales son las bases que estan consumiendo mas memoria puedo analizar dentro de ellas cuales son las tablas/indices que ocupan mas lugar en memoria.
USE DB_que_usa_mucha_memoria --(se saca de la consulta anterior);

WITH src AS(   SELECT       [Object] = o.name,       [Type] = o.type_desc,       [Index] = COALESCE(i.name, ''),       [Index_Type] = i.type_desc,       p.[object_id],       p.index_id,       au.allocation_unit_id   
FROM       sys.partitions AS p   INNER JOIN       sys.allocation_units AS au       ON p.hobt_id = au.container_id   INNER JOIN       sys.objects AS o       ON p.[object_id] = o.[object_id]   INNER JOIN       sys.indexes AS i       ON o.[object_id] = i.[object_id]       AND p.index_id = i.index_id   WHERE       au.[type] IN (1,2,3)       AND o.is_ms_shipped = 0)
SELECT   src.[Object],   src.[Type],   src.[Index],   src.Index_Type,   buffer_pages = COUNT_BIG(b.page_id),   buffer_mb = COUNT_BIG(b.page_id) / 128
FROM   src
INNER JOIN   sys.dm_os_buffer_descriptors AS b  
 ON src.allocation_unit_id = b.allocation_unit_id
WHERE   b.database_id = DB_ID()
GROUP BY   src.[Object],   src.[Type],   src.[Index],   src.Index_Type
ORDER BY   buffer_pages DESC;


En mi caso, el ModelCrossReference que tiene unos 2 millones de registros el que consume mas memoria.


Por otro lado, alguna recomendaciones para el uso de memoria y disco de las KB de equipos de desarrollo.
Es comun que cuando estamos desarrollando, tengamos muchas KB y por lo tanto muchisimas bases SQLServer. Dichas bases en mi caso, las uso un rato y luego las dejo de usar por periodos prolongados.

Para bajar el uso de memoria, es recomendable que las bases se cierren automaticamente cuando se dejan de usar y tambien que se achiquen cuando tienen espacio libre (por ejemplo al borrar una version).

Para esto, uso el siguiente script


 
sp_MSforeachdb '
BEGIN
USE [?]
DECLARE @dbid INT
SET @dbid = DB_ID()
IF(@dbid > 4)
BEGIN
    PRINT ''[?]'' + CONVERT(VARCHAR, @dbid)
    ALTER DATABASE [?] SET AUTO_SHRINK ON
 ALTER DATABASE [?] SET AUTO_CLOSE ON
END
END;
'
Esto NO DEBERIA HACERSE EN SERVIDORES DE PRODUCCION, sino solamente en ambientes de desarrollo, pues no esta recomendado ni el cierre automático , ni el auto_shrink en bases de datos de producción.

Comentarios

Entradas más populares de este blog

Aplicación monolítica o distribuida?

La nefasta influencia del golero de Cacho Bochinche en el fútbol uruguayo

Funcionalidades de GeneXus que vale la pena conocer: DATE Constants.