Estou testando arquiteturas diferentes para tabelas grandes e uma sugestão que vi é usar uma exibição particionada, na qual 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 a "coluna de particionamento" na exibição de fatos, o otimizador procura apenas nas tabelas relevantes. Além disso, se eu filtrar essa coluna na tabela de dimensões, o otimizador eliminará as tabelas desnecessárias.
No entanto, se eu filtrar algum outro aspecto da dimensão, o otimizador procurará no PK / CI de cada tabela base.
Aqui estão as consultas 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.
Estou trabalhando para particionar a tabela maior para ver se a eliminação da partição responde de maneira semelhante.
Eu obtenho eliminação de partição para a consulta (simples) que filtra um aspecto da dimensão.
Enquanto isso, aqui está uma cópia apenas do stats do banco de dados:
https://gist.github.com/swasheck/9a22bf8a580995d3b2aa
O "antigo" estimador de cardinalidade recebe um plano mais barato, mas isso se deve às estimativas mais baixas de cardinalidade em cada uma das buscas (desnecessárias) do índice.
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)
fonte
CREATE STATISTICS [_WA_Sys_00000008_2FCF1A8A] ON [dbo].[Observation_2010]([StationStateCode]) WITH STATS_STREAM = 0x01000000010000000000000000000000D4531EDB00000000D5080000000000009508000000000000AF030000AF000000020000000000000008D000340000000007000000E65DE0007DA5000076F9780000000000867704000000000000000000ABAAAA3C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
ObservationDates
tabela. Não estou conseguindo o mesmo plano que Paul, mesmo com o 4199, e acho que é por isso.ObservationDates
. Acabei rodandoUPDATE STATISTICS ObservationDates WITH ROWCOUNT = 10000
manualmente para obter o plano que Paul demonstrou.ObservationDates
então não tenho certeza do que está acontecendo com isso. Além disso, também não sou capaz de obter o plano que Paulo gerou. vou tentar a atualização para ver.Respostas:
Ative 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. A figura 73.049 veio das informações de Cardinalidade da tabela no anexo do Explorador de plano. Usei o SQL Server 2014 SP1 CU4 (compilação 12.0.4436) com dois processadores lógicos, memória máxima definida como 2048 MB e nenhum sinalizador de rastreamento além do 4199.
Você deve obter um plano de execução que inclua a eliminação dinâmica de partições:
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 retornar verdadeiro é que a Busca de Índice Clusterizado abaixo dele é executada. Portanto, eliminação dinâmica da partição.
Esta é, talvez, não muito eficiente como eliminação de estática, especialmente se o plano é 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 visualizações particionadas (como tabelas particionadas) podem ser complicadas.O ponto é que você precisa de um plano que inclua filtros de inicialização para obter a eliminação dinâmica de partições com visualizações particionadas.
Consultas com
USE PLAN
dicas incorporadas : (via gist.github.com):fonte
Minha observação sempre foi que você deve especificar o valor (ou intervalo de valores) para a coluna da partição explicitamente na consulta, a fim de obter a "eliminação da tabela" em uma exibição particionada. Isso se baseia na experiência do uso de modos de exibição particionados na produção do SQL Server 2000 ao 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 apropriada no lado interno do loop, com base no valor da linha no lado externo do loop. No entanto, como a resposta de Paul explica , existe a possibilidade de um plano com filtros de inicialização para ignorar dinamicamente tabelas irrelevantes no lado interno do loop em tempo constante (ao contrário de logarítmico realizando a busca).
Observe que, para tabelas particionadas, no entanto, esse tipo de busca (para uma partição específica) é suportada.
Se você está decidido a usar visualizações particionadas, outra opção é dividir sua consulta em várias consultas, como:
Isso produz o seguinte plano. Agora existe uma consulta extra que atinge a tabela de dimensões, mas a consulta sobre a tabela de fatos (presumivelmente muito maior) é otimizada.
fonte
20000101
e, em20051231
vez das variáveis (ou faça algo semelhante por meio de duas consultas separadas em seu aplicativo), sim, o mesmo efeito seria alcançado sem o uso das variáveis.