Estou fazendo alguns testes de indexação columnstore em uma única tabela que tem cerca de 500 milhões de linhas. Os ganhos de desempenho em consultas agregadas foram incríveis (uma consulta que antes levava cerca de 2 minutos para ser executada agora é executada em 0 segundos para agregar a tabela inteira).
Mas também notei que outra consulta de teste que aproveita a busca em um índice rowstore existente na mesma tabela agora está sendo 4x mais lenta do que antes antes de criar o índice columnstore. Posso demonstrar repetidamente ao descartar o índice columnstore que a consulta rowstore é executada em 5 segundos e, adicionando novamente no índice columnstore, a consulta rowstore é executada em 20 segundos.
Estou de olho no plano de execução real para a consulta de índice rowstore, e é quase exatamente o mesmo em ambos os casos, independentemente de o índice columnstore existir. (Ele usa o índice rowstore em ambos os casos.)
A consulta de teste do rowstore é:
SELECT *
INTO #TEMP
FROM Table1 WITH (FORCESEEK)
WHERE IntField1 = 571
AND DateField1 >= '6/01/2020'
O índice rowstore usado nesta consulta é:CREATE NONCLUSTERED INDEX IX_Table1_1 ON Table1 (IntField1, DateField1) INCLUDE (IntField2)
A consulta de teste columnstore é:
SELECT COUNT(DISTINCT IntField2) AS IntField2_UniqueCount, COUNT(1) AS RowCount
FROM Table1
WHERE IntField1 = 571 -- Some other test columnstore queries also don't use any WHERE predicates on this table
AND DateField1 >= '1/1/2019'
O índice columnstore é:CREATE NONCLUSTERED COLUMNSTORE INDEX IX_Table1_2 ON Table1 (IntField2, IntField1, DateField1)
Aqui está o plano de execução para a consulta de índice rowstore antes de criar o índice columnstore:
Aqui está o plano de execução para a consulta de índice rowstore depois de criar o índice columnstore:
As únicas diferenças que noto entre os dois planos é que o aviso da operação Sort desaparece após a criação do índice columnstore e os operadores Key Lookup e Table Insert (#TEMP) demoram significativamente mais.
Aqui estão as informações da operação Sort com o aviso (antes de criar o índice columnstore):
Aqui estão as informações da operação Sort sem o aviso (depois de criar o índice columnstore):
Eu teria pensado que uma consulta de leitura que está aproveitando especificamente o mesmo índice de armazenamento de linhas e plano de execução em ambos os casos deveria ter aproximadamente o mesmo desempenho em cada execução, independentemente de quais outros índices existem nessa tabela. O que dá aqui?
Edit: Aqui estão as estatísticas de TIME e IO antes de criar o índice:
Aqui estão as estatísticas depois de criar o índice columnstore:
Adicionar o índice columnstore não clusterizado permite uma classificação no modo de lote no segundo plano de execução. Isso faz com que todo o processamento seja feito em um thread - portanto, mesmo que a consulta tenha um plano paralelo, ela está essencialmente sendo executada em série. Você pode ver isso observando os detalhes dos diferentes operadores.
Reproduzi seu problema localmente, aqui está o operador de classificação com contagens por thread - como você pode ver, tudo está no thread 1:
Observe que o "Modo de Execução Real" é "Lote".
Tudo após a classificação (a junção de loops aninhados, pesquisa de chave etc.) é essencialmente serial, que é o que diminui a velocidade da consulta.
Consulte este artigo da base de conhecimento para obter detalhes e possíveis soluções:
Adiciona o sinalizador de rastreamento 9358 para desabilitar as operações de classificação do modo em lote em uma consulta paralela complexa no SQL Server 2016
Para completar, as opções descritas são:
QUERY_OPTIMIZER_HOTFIXES
opção de banco de dados ou aENABLE_QUERY_OPTIMIZER_HOTFIXES
dica de consulta)Livrar-se do tipo é outra solução para esse problema. A classificação está presente apenas para tentar evitar muita E/S aleatória da junção de loops aninhados, que está usando pré-busca não ordenada, conforme mencionado neste artigo por Craig Freedman:
Otimizando o desempenho de E/S classificando - Parte 1
Você pode se livrar do tipo por:
OPTION (QUERYTRACEON 9115)
à consulta