Estou testando diferentes arquiteturas para tabelas grandes e uma sugestão que vi é usar uma exibição particionada, em que uma tabela grande é dividida em uma série de tabelas "particionadas" menores.
Ao testar essa abordagem, descobri algo que não faz muito sentido para mim. Quando filtro "coluna de particionamento" na visualização de fatos, o otimizador busca apenas nas tabelas relevantes. Além disso, se eu filtrar essa coluna na tabela de dimensões, o otimizador eliminará tabelas desnecessárias.
No entanto, se eu filtrar algum outro aspecto da dimensão, o otimizador busca no PK/CI de cada tabela base.
Aqui estão as perguntas em questão:
select
od.[Year],
AvgValue = avg(ObservationValue)
from dbo.v_Observation o
join dbo.ObservationDates od
on o.ObservationDateKey = od.DateKey
where o.ObservationDateKey >= 20000101
and o.ObservationDateKey <= 20051231
group by od.[Year];
select
od.[Year],
AvgValue = avg(ObservationValue)
from dbo.v_Observation o
join dbo.ObservationDates od
on o.ObservationDateKey = od.DateKey
where od.DateKey >= 20000101
and od.DateKey <= 20051231
group by od.[Year];
select
od.[Year],
AvgValue = avg(ObservationValue)
from dbo.v_Observation o
join dbo.ObservationDates od
on o.ObservationDateKey = od.DateKey
where od.[Year] >= 2000 and od.[Year] < 2006
group by od.[Year];
Aqui está um link para a sessão do SQL Sentry Plan Explorer.
Na verdade, estou trabalhando no particionamento da tabela maior para ver se a eliminação da partição responde de maneira semelhante.
Eu obtenho a eliminação da partição para a consulta (simples) que filtra um aspecto da dimensão.
Enquanto isso, aqui está uma cópia somente de estatísticas do banco de dados:
https://gist.github.com/swasheck/9a22bf8a580995d3b2aa
O estimador de cardinalidade "antigo" obtém um plano mais barato, mas isso ocorre devido às estimativas de cardinalidade mais baixas em cada uma das buscas de índice (desnecessárias).
Gostaria de saber se existe uma maneira de fazer com que o otimizador use a coluna chave ao filtrar por outro aspecto da dimensão para que ele possa eliminar buscas em tabelas irrelevantes.
Versão do SQL Server:
Microsoft SQL Server 2014 - 12.0.2000.8 (X64)
Feb 20 2014 20:04:26
Copyright (c) Microsoft Corporation
Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)
Habilite o sinalizador de rastreamento 4199.
Eu também tive que emitir:
para obter os planos mostrados abaixo. As estatísticas desta tabela estavam ausentes no upload. O valor de 73.049 veio das informações de cardinalidade da tabela no anexo do Plan Explorer. Usei o SQL Server 2014 SP1 CU4 (compilação 12.0.4436) com dois processadores lógicos, memória máxima definida como 2.048 MB e nenhum sinalizador de rastreamento além de 4.199.
Você deve então obter um plano de execução que apresenta eliminação de partição dinâmica:
Fragmento do plano:
Isso pode parecer pior, mas os filtros são todos filtros de inicialização . Um exemplo de predicado é:
Por iteração do loop, o predicado de inicialização é testado e somente se ele retornar verdadeiro é que a busca de índice clusterizado abaixo dele é executada. Portanto, eliminação de partição dinâmica.
Isso talvez não seja tão eficiente quanto a eliminação estática, especialmente se o plano for paralelo.
Pode ser necessário tentar dicas como
MAXDOP 1
,FAST 1
ouFORCESEEK
na exibição para obter o mesmo plano. As opções de custo do otimizador com exibições particionadas (como tabelas particionadas) podem ser complicadas.O ponto é que você precisa de um plano que apresente filtros de inicialização para obter a eliminação dinâmica de partições com exibições particionadas.
Consultas com
USE PLAN
dicas incorporadas: (via gist.github.com):Minha observação sempre foi que você deve especificar o valor (ou intervalo de valores) para a coluna de partição explicitamente na consulta para obter "eliminação de tabela" em uma exibição particionada. Isso se baseia na experiência de usar exibições particionadas na produção do SQL Server 2000 até o SQL Server 2014.
O SQL Server não tem um conceito de operador de junção de loop no qual o mecanismo pode direcionar dinamicamente a busca diretamente para a tabela adequada no lado interno do loop com base no valor da linha no lado externo do loop. No entanto, como explica a resposta de Paul , existe a possibilidade de um plano com filtros de inicialização para pular dinamicamente tabelas irrelevantes no lado interno do loop em tempo constante (em oposição ao logarítmico ao realizar a busca).
Observe que para tabelas particionadas, no entanto, esse tipo de busca (para uma partição específica) é suportado.
Se você está determinado a usar exibições particionadas, outra opção é dividir sua consulta em várias consultas, como:
Isso produz o seguinte plano. Agora há uma consulta extra que atinge a tabela de dimensão, mas a consulta sobre a tabela de fatos (presumivelmente muito maior) é otimizada.