Estou trabalhando com SQL Server e tenho duas tabelas, table1
e table2
. Ambas as tabelas têm uma DATETIME
coluna indicada como dt
. Preciso unir essas tabelas com base não apenas em certas condições, mas também para garantir que as linhas correspondentes tenham a mesma data (a hora não é considerada aqui) da dt
coluna.
Aqui está a consulta que estou usando atualmente:
select *
From table1 a inner join table2 b
on a.id = b.a_id
and convert(date, a.dt) = convert(date, b.dt)
Essa consulta funciona para obter os resultados de que preciso, mas estou preocupado com seu desempenho, especialmente à medida que as tabelas aumentam de tamanho.
Eu estou querendo saber se existem maneiras mais eficazes para alcançar o mesmo resultado? Existem técnicas ou recursos do SQL Server que possam me ajudar a otimizar essa consulta, principalmente a parte de comparação de datas?
Qualquer conselho ou sugestão seria muito apreciada. Agradeço antecipadamente.
computando
Se eu fosse você e tivesse que fazer isso repetidamente, provavelmente adicionaria colunas computadas que fornecem os tipos de dados desejados e as indexaria de acordo.
Obviamente, isso não oferece nenhum benefício real por si só até que as colunas sejam indexadas para suportar a junção.
O bom dessa abordagem é que adicionar as colunas computadas como não persistentes é uma operação rápida e sem bloqueio com quase zero de gravações no banco de dados. Você pode adiar isso para quando adicionar índices (que você precisa de qualquer maneira).
E por meio da parte de correspondência de expressão da otimização de consulta, você nem precisa alterar a consulta original para o SQL Server usar as novas colunas.
Você pode usar um intervalo de datas em uma ou outra tabela
Qualquer tabela que você escolher para usar as funções não pode usar índices, então escolha sabiamente. Teste os dois lados e examine o plano de execução.
No SQL Server 2022 e no Azure SQL, você pode usar
DATETRUNC(day, b.dt)
.Depende...
Se você deseja um loop aninhado com uma busca de índice correlacionada e possui um índice adequado em pelo menos uma das tabelas com colunas iniciais, a
id,dt
conversão em uma busca de intervalo será o ideal, como na resposta de Charlie .Se você deseja uma junção de hash (talvez não tenha índices úteis), então
ou
Pelo menos fornece um predicado de igualdade em ambas as condições, o que significa que ambas podem ser usadas na chave de hash.
DATETRUNC
é mais capaz de tirar proveito do fato de que um índice ordenado pordatetime
também é ordenado pordate
e também permite uma junção de mesclagem com um predicadoid, DATETRUNC(day, dt)
sem nenhum operador de classificação se ambas as tabelas tiverem um índice ativadoid, dt
- embora isso seja um "muitos para muitos " digite com uma mesa de trabalho.A
convert(date, a.dt)
opção também ofereceria suporte a uma pesquisa indexada com loops aninhados e uma igualdadeid
e busca de intervalodt
, embora não tão eficiente quanto construir o intervalo por conta própria, pois a busca dinâmica lê um dia adicional.A lógica de busca dinâmica não se estende a
DATETRUNC
isso, então o melhor que se pode fazer com loops aninhados é uma igualdade naid
parte e residual na data.Dependendo de quanto as tabelas subjacentes são gravadas versus com que frequência elas são lidas com essa consulta, outra opção que você pode considerar é uma exibição indexada .
Uma exibição indexada persistirá os resultados da consulta como se fosse uma tabela em si. Essa compensação de uso de espaço em disco adicional e sobrecarga de gravação beneficia o desempenho de leitura aprimorado - essencialmente como se a consulta estivesse lendo diretamente de uma tabela.
Geralmente, existem algumas limitações de exibições indexadas , mas sua consulta parece se adequar aos critérios que a tornam utilizável para ela. Você pode criar um assim:
Primeiro ceite a visão com a
SCHEMABINDING
opção (listando explicitamente as colunas e chamando seus nomes de esquema, conforme os requisitos):Em seguida, crie um índice clusterizado exclusivo na exibição recém-criada para convertê-lo em uma exibição indexada que persiste no disco:
Por fim, selecione na exibição indexada recém-criada com a
NOEXPAND
dica para garantir que ela use a cópia persistente dos dados:As exibições indexadas também são úteis se você não tiver controle para modificar os índices das próprias tabelas subjacentes.
A solução mais rápida seria adicionar uma coluna de data extra a ambas as tabelas e garantir que ela seja preenchida por qualquer programa que esteja gravando nas tabelas. Atualize os dados existentes com:
Então a consulta existente seria: