Eu tenho uma tabela do SQL Server com mais de 3 bilhões de linhas. Uma das minhas consultas leva um tempo extremamente longo, por isso estou pensando em otimizá-las. A consulta fica assim:
SELECT [Enroll_Date]
,Count(*) AS [Record #]
,Count(Distinct UserID) AS [User #]
FROM UserTable
GROUP BY [Enroll_Date]
O [Enroll_Date] é uma coluna de baixa seletividade com menos de 50 valores possíveis, enquanto a coluna UserID é uma coluna de alta seletividade com mais de 200 milhões de valores distintos. Com base em minha pesquisa, acredito que devo criar um índice composto não agrupado nessas duas colunas e, em teoria, a coluna de alta seletividade deve ser a primeira coluna. Mas não tenho certeza no meu caso, isso funcionaria porque estou usando a coluna de baixa seletividade no grupo por cláusula.
Esta tabela não possui índice clusterizado.
sql-server
index
nonclustered-index
Thinkinger
fonte
fonte
Respostas:
Como alternativa à solução do @ AaronBertrand (se você não pode ou não deseja criar uma exibição indexada), recomendo que você crie um índice
(Enroll_Date, UserID)
. Se esse tipo de pergunta for muito comum na sua tabela, provavelmente esse deve ser o seu índice em cluster.Geralmente, eu não recomendaria índices de alta seletividade como uma "melhor prática" geral, mas observe qual índice oferecerá o melhor desempenho para sua consulta.
Um índice
(Enroll_Date, UserID)
ativado fornecerá à sua consulta um plano de consulta altamente otimizado e sem bloqueio com os agregados de fluxo."Não-bloqueante" neste contexto significa que a consulta não precisa armazenar quantidades significativas de dados (como, por exemplo, uma agregação de classificação ou hash), o que significa que (a) começa a retornar linhas imediatamente e ( b) consome praticamente nenhuma memória de trabalho.
fonte
A resposta de Aarons é uma ótima solução. Responderei à pergunta assumindo que você não deseja adotar essa abordagem.
A consulta que você postou geralmente será executada agrupando primeiro
(Enroll_Date, UserID)
e depois novamente(Enroll_Date)
. Essa otimização é nova no SQL Server 2012. Ela entra em vigor no caso de uma únicaCOUNT DISTINCT
.Um índice nessas duas colunas na ordem específica
(Enroll_Date, UserID)
será suficiente para obter um plano eficiente que canalize uma varredura de índice em dois agregados de fluxo consecutivos. A ordem oposta não permitiria esse plano.Portanto, use o pedido
(Enroll_Date, UserID)
. Você não tem escolha aqui.fonte
Parece um cenário ideal para uma exibição indexada, que permite pagar cálculos e agregações no momento da gravação, em vez do tempo da consulta.
Isso levará algum tempo para criar e, é claro, exigirá manutenção em todas as operações DML, como um índice na tabela base.
Agora, a consulta nessa visualização seria bastante semelhante - cada linha na visualização agora representa uma combinação de usuário / data distinta, para que o número possa ser calculado por uma única COUNT (*), enquanto o número total de linhas na tabela base é já agregado parcialmente para você, agora você só precisa adicioná-los usando SUM por data:
Adicionado NOEXPAND dica, depois de lembrar isso e isso .
Posso dizer sem dúvida que essa consulta será mais rápida que a atual (mas não em quanto), exceto nos casos raros em que você tenha exatamente um usuário para cada data (nesse caso, a mesma quantidade de dados terá para serem lidas) e as colunas que conhecemos são as únicas colunas no índice da tabela base. Se esse aumento de desempenho no momento da leitura vale o trabalho extra que afetará a parte de gravação da sua carga de trabalho é algo que não podemos dizer a você - você precisará testá-lo para medir o trade-off (nenhum índice é gratuito).
E se você costuma usar as mesmas cláusulas WHERE comuns em relação ao Enroll_Date para intervalos específicos e bem definidos (por exemplo, o trimestre ou ano atual), você pode adicionar índices filtrados correspondentes que reduzam ainda mais a E / S (mas sempre há um troca).
Você também pode considerar colocar um índice em cluster na tabela base. Esse não parece ser um daqueles casos de uso muito raros que se beneficiam de uma pilha.
fonte