Eu tenho uma visão que faz referência a uma tabela de fatos Cost com 300 milhões de registros. Essa visão também tem algumas junções. A tabela de fatos tem um índice clusterizado em Data e a definição da visualização é algo assim:
select *
from FactCost f
INNER JOIN SomeOtherTable b on a.id = f.id
where f.Date < getdate()-7
Se eu consultar a exibição como abaixo, o otimizador primeiro processará o predicado na exibição e, em seguida, a data na minha consulta. Então, na verdade, ele lê 300 milhões de registros e retorna apenas 1 milhão. Não consigo descobrir que tipo de solução alternativa posso tentar otimizar isso.
SELECT
*
FROM [dbo].vwFactCost
WHERE Date >= '2011-07-01'
AND Date <= '2011-07-31'
EDITAR
:
Encontrei esse outro cenário em que a solução não era intuitiva.
tabela: FactRegistration
com 300m registros, 30 colunas, RegDate
é coluna de data
abaixo está a definição de visualização:
SELECT <columns>
FROM FactRegistration fr
WHERE FR.RegDate < CAST(DATEADD(DAY,-7,GETDATE()) AS DATE)
consulta:
SELECT <columns>
INTO #tmp
FROM edw.dbo.vwDemo_slow fr
WHERE fr.RegDate >= CAST('20140501' AS DATE)
AND fr.RegDate <= CAST('20140531' AS DATE)
Resultados neste plano ( https://gist.github.com/gflores1023/f0f0089315841d21ab072837cf12145d ):
Se eu alterar a definição de exibição para usar esta cláusula WHERE:
WHERE FR.RegDate < CAST(CAST(DATEADD(DAY,-7,GETDATE()) AS DATE) AS DATETIME)
Eu recebo um plano muito melhor ( https://gist.github.com/gflores1023/e3904609c98babbbbc646eaec76ebba4 ):
Executando o SQL Server 2016 SP1
Eu sugeriria:
getdate()-7
para a adequada e explícitaCONVERT(datetime2(2), DATEADD(DAY, -7, GETDATE()))
SELECT *
em todos os lugares, especialmente na vistaEntão:
Isso não apenas protege contra conversões implícitas e interpretação ydm, como também é muito mais fácil encontrar o início do próximo mês do que o final do mês atual.