Como aumentar o desempenho de consultas virgens no MS SQL Server?


10

Eu tenho o site ASP.NET que possui seu próprio cache independente de dados e os dados não são alterados por longos períodos de tempo, portanto, não é necessário consultar o SQL Server pela segunda vez com a mesma consulta. Preciso melhorar o desempenho das primeiras consultas (virgens) que vão para o SQL Server. Algumas consultas processam tantos dados que podem causar o uso do SQL Server tempdb. Como eu não uso variáveis ​​de tabela temporária ou tabelas temporárias, o SQL Server decide usar tempdbsozinho sempre que necessário.

Meu tamanho de db é 16Gb, tenho 32Gb de RAM física disponível na minha máquina servidor.

Entendo que a estratégia de cache do MS SQL Server tenta manter os dados na RAM para acelerar o desempenho de consultas semelhantes, se eles precisarem que os mesmos dados sejam carregados novamente. Além disso, tentará usar a RAM disponível em vez do tempdb para acelerar o desempenho sem causar acesso ao disco.

Suponho que quando a consulta que precisa armazenar algo no SQL Server tempdb chegar e não houver RAM suficiente disponível, o SQL Server terá 2 opções:

1) descarregar alguns dados em cache e usar RAM poupada em vez do tempdb para evitar gravações em disco

2) mantenha os dados armazenados em cache para consultas futuras e comece a usar o tempdb, o que causa gravações no disco lento.

Não sei que escolha o SQL Server fará nessa situação, mas gostaria que fizesse a opção 1, porque me preocupo apenas com o desempenho de consultas primárias (virgens), porque nunca mais envio a mesma consulta ao SQL Server novamente (embora eu possa enviar uma consulta semelhante).

O que é a estratégia de cache do SQL Server para esse cenário?

Como ele equilibra o uso da RAM entre evitar o tempdb para consultas virgens e a velocidade de consultas secundárias?

É possível configurar o SQL Server de forma que faça a escolha nº 1? Se sim, então como?

De que outra forma posso melhorar o desempenho de todas as consultas SQL virgens?

Como não sei sobre a estratégia de cache do SQL Server, quero colocar o banco de dados no disco RAM. Isso garantirá que qualquer consulta virgem tenha alta velocidade de carregamento de dados não armazenados em cache, mesmo que o SQL Server sempre faça a escolha nº 1. O risco disso é que o SQL Server comece a usar mais tempdb com menos RAM disponível (restam apenas 16 Gb depois que eu uso 16 Gb para o disco RAM) se ele continuar fazendo a opção 2, o que atrasará as consultas virgens que causam vazamentos tempdb.

Estou interessado na solução para o SQL 2008 R2, mas acho que provavelmente é o mesmo para o SQL 2008, SQL 2005 e pode ser o SQL 2000.

Esclarecimentos:

Não há outros aplicativos em execução nessa caixa, ele é dedicado ao SQL Server . O site é executado em caixa separada.

É o SQL Server 2008 R2 Standard Edition de 64 bits no Windows Server 2008 R2 Enterprise de 64 bits.

Eu executo apenas consultas somente leitura e o banco de dados está definido como somente leitura .

Vamos supor que já existem bons índices . Esta pergunta é sobre o SQL Server fazer a escolha nº 1 versus a opção nº 2, como é que se faz, se existe uma maneira de controlá-lo e se o disco RAM o ajuda a fazer a escolha certa para consultas virgens.


O que faz você pensar que o tempdb está sendo usado, mesmo que você não esteja criando tabelas temporárias? Você está usando distintas ou agrupadas por tabelas?
darin strait

3
32/64 bits? Físico ou virtual? Este servidor é dedicado ao SQL Server ou você também está executando o IIS ou outros aplicativos na mesma caixa? Você já fez alguma análise do plano de execução da consulta? Você pode postar consultas de exemplo e / ou planos de execução? E mais um para dar sorte ... siga o guia do Kendra para registrar sp_whoisactive enquanto sua consulta de problema estiver em execução e publique a saída.
Mark Storey-Smith

@darinstrait A explicação mais provável seria uma espécie ou vazamento de hash.
Mark Storey-Smith

Respostas:


7

Sua pergunta pode ser basicamente reformulada como 'Como a concessão de memória de consulta funciona?'. Uma boa leitura sobre o assunto é Noções básicas sobre concessão de memória do servidor SQL . Antes de uma consulta ser lançada em execução, pode ser necessária uma concessão de memória para classificações e hashes e outras operações com fome de memória. Essa concessão de memória é uma estimativa . Com base no estado atual do sistema (número de solicitações em execução e pendentes, memória disponível etc.), o sistema concede à consulta uma concessão de memória até a quantidade necessária. Depois que a memória é concedida, a consulta inicia a execução (pode ser necessário aguardar na temida fila 'semáforo de recursos' antes de obter a concessão). Na execução, a concessão de memória é garantidapelo sistema. Essa quantidade de memória pode ser compartilhada com as páginas de dados (já que elas sempre podem liberar no disco), mas nunca com outro uso de memória (ou seja, não pode ser "roubado"). Portanto, quando a consulta começar a solicitar memória confirmada de sua concessão, o mecanismo implantará o que você chama de 'estratégia nº 1': as páginas de dados podem ser despejadas (liberadas se estiverem sujas) para fornecer à consulta a memória prometida. Agora, se a estimativa estiver correta e a concessão corresponder a 100% da memória solicitada, a consulta não deve ser "derramada". Porém, se a estimativa estiver incorreta (se resume a estimativas de cardinalidade, portanto, está sujeita a estatísticas obsoletas) ou se a consulta não recebeu toda a concessão solicitada, a consulta será "derramada". É quando o tempdb entra em cena e o desempenho geralmente é de tanques.

O único botão que você tem à sua disposição que controla algo nesse processo é o Administrador de Recursos . Como o RG pode ser usado para especificar uma configuração MIN para um pool, ele pode ser usado para reservar memória para uma determinada carga de trabalho, para que ele realmente obtenha a concessão de memória solicitada. Obviamente, depois que você fez a investigação adequada que mostra que as concessões de memória reduzidas são as culpadas e, é claro, depois que o impacto em outras cargas de trabalho foi avaliado. E testado, é claro.

Agora vamos voltar à sua pergunta original. Se sua investigação estiver correta (muito se), gostaria de destacar dois problemas:

  • você executa consultas de produção que exigem concessões de memória para um site . Este é um grande não-não. As concessões de memória são indicativas de consultas analíticas que não têm lugar para servir solicitações HTTP.
  • suas consultas provavelmente não estão recebendo a concessão de memória solicitada. Novamente, ainda mais um não-não para uma carga de trabalho crítica de latência como os sites.

Então, o que isso me diz é que você tem um problema fundamental de design e arquitetura. Os sites são controlados por latência e devem criar uma carga de trabalho semelhante a OLTP, sem concessões de memória e sem pressão de memória nas consultas. Sem mencionar nenhum derramamento. As consultas analíticas devem ser executadas em trabalhos offline e armazenar os resultados pré-processados ​​para disponibilidade rápida quando as solicitações HTTP desejarem.


@ Mark: A maioria das consultas não requer concessão de memória. Apenas alguns operadores (principalmente a classificação e a junção de hash) precisam de um buffer de trabalho e, portanto, solicitam uma concessão. Essa é a 'nomenclatura' padrão. Você pode estar pensando no ambiente de execução e no plano de execução de consultas, dos quais cada consulta exige uma e inclui alguma memória. Uma concessão de memória é muito maior (MBs). Em segundo lugar, observe sys.dm_exec_query_memory_grants: você tem requested(o máximo), required(o mínimo) e granted(o real).
Remus Rusanu

Desculpas. Eu peguei de algum lugar que o mínimo por consulta foi alocado no mesmo funcionário da memória, o que estava incorreto.
Mark Storey-Smith

Ainda não tenho certeza se concordo com seus dois pontos principais. Todo tipo de operações triviais e de junção de hash exigem subvenções no nível mínimo, portanto, sugerir que elas devam ser totalmente eliminadas parece excessivo. Que derramamentos para tempdb de subsídios insuficientes são uma bandeira vermelha é certamente razoável, mas uma proibição geral de qualquer operação que exija uma concessão pode colocar muitas pessoas em um caminho de otimização preventivo desnecessário?
Mark Storey-Smith

O OP alega que possui todos os índices necessários. Se isso for verdade e a carga de trabalho tiver problemas de concessão (e até vazamento) de memória suficientes para serem notados, então eu diria que a carga de trabalho é analítica demais para um site . Em última análise, a otimização do desempenho é sempre um jogo de investigação para determinar a causa raiz. Todas as declarações e proibições gerais sempre são encontradas como um contra-exemplo que as prova erradas, isso é um dado. O OP tem um problema de design que cria uma carga de trabalho analítica demais? Eu não sei. Eu acho que sim? Eu diria que 87,5% de confiança sim.
Remus Rusanu

@Remus: Seu palpite foi bom, as consultas no meu site são 100% analíticas. Ele permite que os usuários construam quaisquer consultas possíveis na interface do usuário para enviar qualquer combinação possível de filtros, agregados e agrupamentos ao SQL Server (o que, é claro, dificulta a indexação). Sim, eu poderia fazê-los executar no modo assíncrono, salvando resultados para recuperação posterior, mas o objetivo é fazer com que qualquer consulta seja executada tão rapidamente que o resultado esteja disponível imediatamente após 2 a 10 segundos e também a consulta analítica é a única função desse site , Acho que fazê-los assíncronos só faz sentido se houver outras consultas que não sejam analíticas.
alpav

3

O que você não mencionou é que tipo de consulta é executada no banco de dados e se existem índices corretos para acelerar o desempenho de suas consultas.

Você também precisa verificar se há outros aplicativos em execução na mesma caixa. Mesmo que a caixa tenha 32 GB de RAM, você definiu qualquer configuração de memória máxima no servidor de banco de dados para colocar qualquer limite artificial. Se houver aplicativos em execução no mesmo servidor, o SQL e os outros aplicativos poderão estar competindo por recursos e observe que o SQL está com muita memória.

O SQL Server usará o tempdb para classificação interna ou junções / agregados de hash / operadores de spool etc. e você não poderá controlar esse comportamento. O que você pode fazer é limitar a quantidade de dados retornados.

Você verificou as estatísticas de espera nesta caixa? Sempre que o SQL Server está aguardando um recurso, o SQL Server rastreia o recurso de espera e olha para essas informações.

Observe as consultas de diagnóstico de Glenn Berry e isso será um bom começo para você.

Consulte também PARAMETERIZATION FORCED, conforme mencionado em http://weblogs.sqlteam.com/dang/archive/2009/06/27/Forced-Parameterization-A-Turbo-Button.aspx


ok, vamos assumir que já existem índices corretos. Esqueci de mencionar que este é um banco de dados somente leitura com consultas somente leitura e não há outro aplicativo em execução na caixa do SQl Server.
alpav

Suas estatísticas estão atualizadas? Os bancos de dados somente leitura não podem criar estatísticas se estiverem ausentes ou desatualizados. Seus dados estão distorcidos ou têm valores exclusivos para a chave. Existem muitos fatores que podem causar esse comportamento.
Sankar Reddy

O que você quer dizer com "esse comportamento"? Eu não mencionei que algo está errado. Eu só quero melhorar o desempenho em minhas circunstâncias especiais. O SQL Server é otimizado para ser executado em qualquer situação, mas pode ou não ser executado da melhor maneira na minha situação. Não tenho certeza se posso confiar no SQL Server para fazer uma escolha equilibrada nº 1 versus nº 2. Toda vez que coloco novos dados, executo sp_updatestats.
alpav


2
Quando você está executando sp_updatestats, qual é a taxa de amostra que você escolheu. A proporção padrão é muito amostra e depende do tamanho do índice. Se suas consultas consultarem principalmente (apenas) os novos dados e mesmo se você fizer sp_updatestats, o SQL Server não poderá tomar decisões divinas nos planos de execução.
Sankar Reddy

2

Atualmente, esta pergunta parece uma solução que procura um problema. Você decidiu que um disco RAM é a solução e deseja que alguém valide essa escolha. Desculpe, não vai acontecer.

Se você mediu e observou um derramamento no tempdb, isso quase certamente se deve a uma operação de classificação ou hash e a uma concessão insuficiente de memória de consulta. Dependendo do volume de dados a ser processado, isso pode ser inevitável, mas há boas chances de que a consulta e / ou indexação possam ser melhoradas para evitá-lo.

Dê uma olhada no Buffer Management para entender melhor como o SQL Server gerencia a memória e o SQL Server Memory Management Explained para algumas ferramentas básicas e consultas DMV para entender onde sua memória está alocada.

De que outra forma posso melhorar o desempenho de todas as consultas SQL virgens?

Este é um grande tópico. Poste a consulta e planeje e você receberá um feedback direcionado.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.