Maior RAM, pior desempenho

9

Configuração:

  • Windows Server 2008 R2
  • SQL Server 2008 R2 SP1
  • 240GB RAM
  • TempDB são arquivos de dados de 8x16GB sem crescimento automático (total de 128GB)
  • Servidor Físico / Independente

Este servidor é usado para processamento ETL. Acabamos de instalar mais RAM neste servidor, totalizando 240 GB de RAM. Os serviços do SQL Server são as únicas coisas reais em execução.

A memória aparece bem no BIOS, OpenManage e Windows.

Se eu configurar o SQL Server para usar um mínimo / máximo de 70 / 100GB de memória, não haverá problemas. No entanto, depois que eu aumentar para 120 / 150GB, recebo o seguinte erro ao executar um dos nossos processos ETL:

Não foi possível alocar espaço para o objeto '<objeto temporário do sistema: 422234507706368>' no banco de dados 'tempdb' porque o grupo de arquivos 'PRIMARY' está cheio. Crie espaço em disco excluindo arquivos desnecessários, descartando objetos no grupo de arquivos, adicionando arquivos adicionais ao grupo de arquivos ou configurando o crescimento automático para arquivos existentes no grupo de arquivos. (Mensagem 1105, estado 2, procedimento desconhecido, linha 1)

Nunca encontramos esse problema antes de alterar a configuração da memória. Depois de reconfigurar o original para 70 / 100GB, não recebemos esse erro.

Coisas que tentei:

  1. Defina os arquivos de dados TempDB para crescimento automático. Isso simplesmente resulta no crescimento automático dos arquivos até que a capacidade do disco seja atingida e falhe.
  2. Adicione mais arquivos de dados TempDB. Mesmo erro que o mostrado.
  3. Aumente o tamanho do TempDB para 8x32GB (total de 256GB)

Estou sem saber o que poderia estar causando esse problema.

Derek Kromm
fonte
2
Sua memória está equilibrada nos nós NUMA? E os seus processadores? O log do SQL Server mostra quantas CPUs estão em uso durante a inicialização?
Aaron Bertrand
11
O que você está usando para os processos ETL? SSIS ou alguma ferramenta similar? Se for uma ferramenta fora do SQL Server, você a está executando no mesmo servidor que sua instância do SQL Server?
Mike Fal
11
Esse é um bom argumento, @Mike, se o processo ETL não conseguir recuperar memória suficiente, porque o SQL Server está usando muito, talvez seja necessário enviar o trabalho para tempdb.
Aaron Bertrand
11
Aqui está um bom começo para monitorar o uso do tempdb: msdn.microsoft.com/en-us/library/ms176029(v=SQL.105).aspx . Isso deve lhe dar uma idéia do que está acontecendo.
Thomas Stringer
2
Você já fez alguma análise do que está realmente sendo executado quando o TempDB está realmente se expandindo? Um sp_who2 / sp_whoisactive simples? Parece-me que você tem algumas transações de longa duração que podem ser melhor gerenciadas, mas difíceis de dizer. Pessoalmente, eu não conseguiria me apegar à alteração de memória, mas observe primeiro o código e veja se está funcionando corretamente.
Mike Fal

Respostas:

3

Obrigado a todos por sua ajuda.

Após analisar alguns planos de execução, verifica-se que um JOIN está sendo processado de maneira diferente com base na quantidade de RAM disponível. Com menos RAM, ele é avaliado com um Hash; com mais RAM, ele usa uma série de junções de mesclagem.

Então, basicamente, tudo se resumiu ao T-SQL mal escrito, que estou refatorando atualmente.

Derek Kromm
fonte
4
Isso é contra-intuitivo, porque uma junção de hash requer uma concessão de memória, enquanto a mesclagem não. Existe uma operação de classificação adicional para oferecer suporte à junção de mesclagem?
Martin Smith
1

Esta não é uma resposta para a pergunta, apenas um código que eu não queria postar em um comentário. Para ver o equilíbrio de seus agendadores e memória nos nós NUMA (e também para ver se algum nó não está visível online):

SELECT 
  parent_node_id, 
  [status],
  AVG(current_tasks_count) AS avg_tasks_count, 
  AVG(load_factor) AS avg_load_factor,
  scheduler_count = COUNT(*)
FROM sys.dm_os_schedulers
GROUP BY parent_node_id, [status];

SELECT 
  memory_node_id, 
  name, 
  SUM(single_pages_kb + multi_pages_kb) AS memory_kb
FROM sys.dm_os_memory_clerks
GROUP BY memory_node_id, name;

(No SQL Server 2012, o último SUMdeve ser, SUM(pages_kb)pois não há mais alocadores separados de uma e várias páginas.)

Aaron Bertrand
fonte