Vous êtes sur la page 1sur 4

Casos do Dia a Dia Diminundo um problema de memria no SQL

Server
25, dezembro, 2010Fabricio LimaDeixar um comentrioIr para os comentrios

Fala Pessoal,
Em meu ambiente de trabalho, possuo um servidor 32 bits com o SQL Server 2005 32
bits, com 4 GB de memria e com a opo /3GB habilitada. Esse servidor possui uma mdia
de 1500 conexes simultneas no banco de dados durante o horrio de pico e possui 200 Gb
de dados. Repetindo, 200 GB de dados e 4 GB de memria.
Como pode ser visto na figura abaixo, o servio do SQL Server consegue utilizar 2.51 GB de
memria nesse servidor.

Essa informao foi gerada com a query abaixo:


select counter_name ,cntr_value,cast((cntr_value/1024.0)/1024.0 as numeric(8,2)) as Gb
from sys.dm_os_performance_counters
where counter_name like %server_memory%;
Vocs devem concordar comigo que 2.51 GB de memria muito pouco para a quantidades
de dados que possuo. Com a query abaixo possvel verificar o contador Page Life
Expectancy, que a expectativa de vida em segundos de uma pgina de dados na memria.
No meu ambiente, esse contador tinha uma mdia entre 30 e 40 segundos durante o dia,
sendo que um nmero considervel aceitvel para esse contador acima de 300 segundos.
SELECT cntr_value AS Page Life Expectancy
FROM sys.dm_os_performance_counters
WHERE object_name = SQLServer:Buffer Manager
AND counter_name = Page life expectancy
Resultado:

Antes de realizar uma reestruturao nos meus ndices (criar missed index, alterar o
fillfactor, excluir ndices duplicados e excluir indices no utilizados), esse contador tinha uma
mdia abaixo de 20 segundos em determinadas horas do dia.
Buscando uma forma de amenizar esse problema(at que seja realizado um upgrade de
Hardware), dei uma boa pesquisada sobre memria e verifiquei que desses 2.51 GB de
memria, o SQL Server estava utilizando 1.5 GB de memria para outros tipos de cache
diferentes do Data Cache (Buffer Pool).
Olha que absurdo, 1.5 GB para alguns caches (Ex: Caches de Plano de Execuo de
Procedures e de Adhoc Querys) e apenas 1 GB para o Buffer Pool, onde realmente esto as
paginas de dados que so utilizadas por qualquer manipulao de dados no SQL Server.
Quando voc realiza uma consulta, caso as pginas de dados que sua consulta deveria
retornar no estejam no Buffer Pool, as pginas so lidas do disco, armazenadas no Buffer
Pool e em seguida so retornadas para a sua consulta. Ou seja, quanto maior for o tamanho
do Buffer Pool, mais pginas de dados sero armazenadas na memria, menos leituras sero
realizadas no disco e, consequentemente, o ganho de performance ser muito grande.

Executando as querys abaixo, foi possvel identificar o quanto de memria estava sendo
utilizado por alguns tipos de Cache do SQL Server:
Utilizao por tipo de cache
SELECT type, SUM(single_pages_kb)/1024. AS [SPA Mem, MB],SUM(Multi_pages_kb)/1024.
AS [MPA Mem,MB]
FROM sys.dm_os_memory_clerks
GROUP BY type
HAVING SUM(single_pages_kb) + sum(Multi_pages_kb) > 40000 S os maiores
consumidores de memria
ORDER BY SUM(single_pages_kb) DESC
Total utilizado
SELECT SUM(single_pages_kb)/1024. AS [SPA Mem, KB],SUM(Multi_pages_kb)/1024. AS
[MPA Mem, KB]
FROM sys.dm_os_memory_clerks
A figura abaixo mostra como estava o resultado dessas querys no meu ambiente no horrio
de produo.

O CACHESTTORE_OBJCP o cache das Stored procedures, Triggers e Functions.


O CACHESTORE_SQLCP o cache de Ad-hoc queries e no muito reutilizado pelo SQL
Server, pois para uma mesma consulta com parmetros diferentes, so gerados dois planos
de execues diferentes.
O USERSTORE_TOKENOERM o cache que armazena vrias informaes de segurana que
so utilizadas pela Engine do SQL Server.
Analisando essas informaes, tomei as seguintes medidas:
Como o CACHESTTORE_OBJCP muito reutilizado, no mechi no mesmo pois poderia piorar
ainda mais meu problema de performance. Se no meu servidor tivesse a verso do SQL
Server 2008, eu poderia excluir individualmente do cache alguns planos de execuo que
ocupam mais espao na memria e so poucos utilizados. Mas como ainda est na verso do
SQL Server 2005, no tive o que fazer.
J os caches CACHESTORE_SQLCP e USERSTORE_TOKENOERM, que ocupavam juntos mais
de 1 GB de memria, me ajudariam bastante liberando memria para o Buffer Pool.
Entretanto, limpando o cache CACHESTORE_SQLCP eu aumentaria meu consumo de CPU
pois incrementaria o nmero de compilaes de algumas querys. Todavia, como meu gargalo
memria, resolvi limpar esses caches assim mesmo.
Criei uma Stored Procedure que roda de 3 em 3 minutos para realizar a limpeza desses
caches e ainda armazeno um log da frequencia com que esses caches so limpos em uma
tabela para histrico conforme os scripts abaixo:
CREATE TABLE [dbo].[Log_Limpeza_Cache](
[Id_Log] [int] IDENTITY(1,1) ,
[Dt_Limpeza] [datetime] ,

[Tipo_Cache] [varchar](30) ,
[Tamanho_MB] [numeric](15, 2) )
CREATE PROCEDURE [dbo].[stpLimpa_Memory_Cache]
AS
BEGIN
DECLARE @USERSTORE_TOKENPERM numeric(15,2), @CACHESTORE_SQLCP numeric(15,2)
SELECT @CACHESTORE_SQLCP = SUM(single_pages_kb+Multi_pages_kb)/1024.
FROM sys.dm_os_memory_clerks
WHERE type = CACHESTORE_SQLCP
SELECT @USERSTORE_TOKENPERM = SUM(single_pages_kb+Multi_pages_kb)/1024.
FROM sys.dm_os_memory_clerks
WHERE type = USERSTORE_TOKENPERM
IF @USERSTORE_TOKENPERM > 30
begin
insert into Log_Limpeza_Cache(Dt_Limpeza,Tipo_Cache,Tamanho_MB)
select getdate(), USERSTORE_TOKENPERM, @USERSTORE_TOKENPERM
DBCC FREESYSTEMCACHE(TokenAndPermUserStore)
end
IF @CACHESTORE_SQLCP > 60
begin
insert into Log_Limpeza_Cache(Dt_Limpeza,Tipo_Cache,Tamanho_MB)
select getdate(), CACHESTORE_SQLCP, @CACHESTORE_SQLCP
DBCC FREESYSTEMCACHE(SQL Plans)
end
END
Aps a primeira limpeza do cache(momentos de tenso), fiquei acompanhando meu trace
com as querys mais demoradas do banco de dados para ver se teria algum problema de
performance. Entretanto, isso no aconteceu. Pelo contrrio, a quantidade de querys lentas
diminuram.
Aps alguns minutos, analisando os contadores de performance, o Page life Expectancy
passou a ter uma mdia entre 100 e 120 segundos. Simplesmente triplicou.
Meu buffer pool, aumentou para mais de 2 GB, ou seja, a quantidade de dados que o SQL
Server disponibiliza em memria para ser utilizada sem acessar o disco dobrou. Eu verifico
essa informao com a query abaixo:
SELECT DB_NAME(database_id) AS [Database Name],
COUNT(*) * 8/1024.0 AS [Cached Size (MB)]
FROM sys.dm_os_buffer_descriptors
WHERE database_id > 4 - exclude system databases
AND database_id <> 32767 - exclude ResourceDB
GROUP BY DB_NAME(database_id)
ORDER BY [Cached Size (MB)] DESC;
Como j era esperado, tambm tive um aumento de processamento e de recompiles, mas o
benefcio da liberao de memria foi maior para o meu ambiente. O nmero de
procedimentos demorando mais de 3 segundos diminuu consideravelmente.
Alm dessa alterao, fiz muitas outras alteraes de performance para esse servidor
aguentar o grande aumento de acesso que temos no Banco de Dados nesse Natal, mas

acredito que essa alterao foi a que fez a maior diferena e me proporcionou um Natal bem
tranquilo. Um excelente presente de Natal.
Claro que antes de realizar essas alteraes no meu servidor de produo, testei em outros
servidores menos crticos. Deixo essa experincia para quem possui um ambiente com esse
mesmo tipo de problema. Espero que possa ter ajudado.
Abraos
Fabrcio Frana Lima

Vous aimerez peut-être aussi