Estou tentando melhorar esta consulta. Quando executo isso como usuário, ele é executado em aproximadamente 1 minuto, mas durante o carregamento do ETL pode levar até 40 minutos. Não deve haver problemas de bloqueio porque essas tabelas não são referenciadas em nenhum outro lugar.
Com base no plano de consulta, que direção devo seguir?
Posso melhorar minha indexação. Ele usa correspondências de hash e mesclagens podem melhorar isso com a indexação.
Preciso de uma abordagem que não seja uma série de LEFT JOINs?
Os nomes das colunas e tabelas foram ofuscados:
Aqui estão alguns cálculos aproximados de onde o tempo foi gasto em seu plano de execução:
Portanto, há um gargalo claro na consulta: a junção com #Cohort_1. O SQL Server está estimando um tamanho de linha de 12 KB dessa tabela, então suponho que você tenha algumas colunas LOB nessa tabela. Existem algumas restrições nos dados LOB para junções de hash no modo em lote. Provavelmente é por isso que você vê algumas junções de hash no modo de lote e, em seguida, o plano muda para o modo de linha com a junção de mesclagem cara junto com outras junções de hash no modo de linha.
Em geral, eu seguiria uma abordagem: obter um plano de consulta com junções de mesclagem em modo de linha ou obter um plano principalmente com junções de hash em modo de lote. Todas as suas tabelas têm a mesma contagem de linhas e se unem na mesma coluna, portanto, as junções de mesclagem podem funcionar bem aqui, mas a consulta pode precisar ser executada em MAXDOP 1 para melhor desempenho. Recomendo obter planos de consulta reais para os seguintes casos de teste:
OPTION (HASH JOIN, LOOP JOIN)
dica e reescrevendo a consulta para que #Cohort_1 junte-se no finalOPTION (MERGE JOIN)
dica à consultaVocê também expressou preocupação com o fato de a consulta poder levar até 40 minutos durante o ETL, o que é muito mais longo do que o observado em seus testes. A maneira mais básica de solucionar isso é habilitar o Query Store e procurar diferenças entre quais logs do Query Store e o que você viu em seus próprios testes. Os planos de consulta são diferentes? As estatísticas de espera são diferentes? Uma consulta usa mais CPU que a outra? Todas essas informações estão disponíveis no SQL Server 2019. Você não precisa adivinhar se houve ou não bloqueio. O Query Store lhe dirá isso.
Em um comentário, você disse o seguinte:
Considero esta uma declaração ofensiva. Os DBAs não funcionam para servir o banco de dados. Eles devem trabalhar para atender os usuários finais. Os usuários finais incluem você, o desenvolvedor. Se eles quiserem assumir a posição de que não podem ativar o Query Store devido à sobrecarga (o que é quase certamente errado), eles precisarão fornecer as informações necessárias de alguma outra forma. Pode ser necessário encaminhar esse problema para a gerência ou tentar encontrar algum tipo de compromisso. Por exemplo, se a carga de trabalho ETL for executada apenas à noite, talvez o Query Store possa ser ativado apenas durante a noite. Mas garanto que se os DBAs tivessem um problema pelo qual fossem responsáveis, eles habilitariam os diagnósticos necessários em vez de dar desculpas sobre sobrecarga.
Observe o plano real para quando a consulta for demorada e as estatísticas de espera dirão o porquê.
Ou ative o Query Store e observe as estatísticas de espera .
Do ponto de vista do design, é estranho ter várias tabelas de preparação de coorte separadas em vez de uma mais ampla. E usar columnstore em tabelas temporárias é estranho. Eles são caros para construir e é caro reconstruir e gerar todas as linhas para um columnstore. É mais barato fazer isso com um índice heap ou clusterizado.
Para um plano de consulta como esse, com índices columnstore como fonte para alguns dos operadores de aquisição de dados, eu iria na direção oposta.
OPTION(HASH JOIN)
no final da consultaMAXDOP 8
também a dicaAs junções de mesclagem não suportam o modo em lote - e há pelo menos um em seu plano - onde as junções de hash o fazem.
Provavelmente seria melhor operar inteiramente em modo lote, em vez de ter algumas operações em modo linha e alternar em vários pontos do plano.
O objetivo do aumento do DOP é espalhar a distribuição de linhas por thread para que mais threads tenham menos linhas para processar simultaneamente, o que provavelmente também melhorará o tempo do relógio de parede ao custo de tempo adicional de CPU.
Além do que outro disse.
i) Observe o sinal de aviso no plano de consulta e elimine o aviso de conversão. Por que converter
Personid
para varchar?ii) Embora a consulta pareça muito simples, o design da tabela parece ser falho, devido ao qual o otimizador fica sobrecarregado. Ligado e média. cada temperatura contém dados de 33L. Muitos deles também são de tipo de dados grandes.
iii) Tente outro método, insira todos os personid e outras colunas primeiro
Staging.CohortStagingTemp AS A
. Em seguida, atualizeProject.BaseTable_STG
com cada tabela temporária usando a junção interna, um, seja um.