Configuração
Em um datawarehouse, estou juntando uma tabela de fatos a 20 dimensões. A tabela de fatos possui 32 milhões de linhas e 30 colunas. Esta é uma tabela temporária, portanto não preciso lidar com outros usuários que leem ou escrevem na tabela. Seleciono 10 colunas da tabela base e 20 colunas das respectivas dimensões. As tabelas de dimensões são pequenas (entre 3 e 15.000 linhas). Os campos nos quais são unidos são números inteiros e nvarchars. Eu uso uma instrução SELECT ... INTO. Não há índices nas tabelas.
A velocidade de execução desta consulta é muito lenta para ser útil.
Soluções experimentadas
Como a consulta leva muito tempo para ser processada, tentei as seguintes soluções:
- Divida as 20 junções em 4 junções em 5 tabelas. O desempenho da consulta permanece baixo, no entanto.
- Coloque índices nas colunas de chave estrangeira. Nenhuma redução significativa de tempo.
- Verifique se os campos da condição de junção são inteiros. Percebi um aumento de desempenho de 25%. Não é exatamente o que estou procurando.
- Use uma inserção na instrução em vez de selecionar em. Desempenho pior devido ao crescimento do arquivo de log, embora o banco de dados esteja no modo de recuperação simples.
Essas descobertas levaram-me a incluir o plano de execução real, que mostra que 89% do custo está na inserção da tabela . Os outros custos são 8% de varredura da tabela na tabela de fatos e 2% na correspondência de hash para as junções internas.
Questões
- Quais são os possíveis motivos da inserção lenta da tabela?
- Quais são as maneiras de identificar esse gargalo sem o plano de execução?
- Quais ações posso tomar para reduzir o custo da inserção da tabela?
fonte
Respostas:
Leia Como analisar o desempenho do SQL Server , especialmente a parte sobre Analisando os tempos de espera de execução de consultas individuais .
Isso dependeria amplamente do resultado da análise de desempenho. Em primeiro lugar, verifique se a parte SELECT é o mais rápida possível. Supondo que esse problema seja a inserção totalmente registrada de thread único, algumas soluções são:
Use a opção de partição para mover 'os' dados. Essa é, de longe, a melhor solução. Prepare os dados intermediários em uma tabela intermediária separada e, em seguida, troque essa tabela intermediária para a tabela DW. Leia Transferindo dados com eficiência usando a alternância de partições .
Verifique se o INSERT está minimamente registrado. Leia operações que podem ser registradas minimamente e pré - requisitos para o registro mínimo . Mesmo se você usar operações de comutação de partição, ainda vale a pena garantir que a compilação da tabela temporária seja minimamente registrada.
Verifique se o seu subsistema de E / S é capaz de gerar uma carga rápida. Leia Introdução aos SSDs .
fonte
Abaixo está a minha experiência e pode ajudar alguém por aí.
Estávamos tentando transferir alguns dados de um banco de dados para outro, também fazendo algumas transformações no caminho. Testando a transformação, estávamos fazendo muitas inserções, corrigindo as coisas ao longo do caminho e excluindo para testar a inserção novamente. No entanto, após algumas inserções e truncamentos, nossas consultas começaram a ficar lentas e uma inserção simples começou a levar até 9 minutos, enquanto estava em execução por cerca de 3 minutos.
Portanto, tente essas duas estratégias e veja como isso funciona para você.
fonte