Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Maneira mais rápida para esta consulta (qual é a melhor estratégia) dado um intervalo de datas


Atualização:

Veja este artigo em meu blog para uma estratégia de indexação eficiente para sua consulta usando colunas computadas:

A ideia principal é que apenas calculamos length arredondado e startDate para seus intervalos e procure-os usando condições de igualdade (que são boas para B-Tree índices)

Em MySQL e no SQL Server 2008 você pode usar SPATIAL índices (R-Tree ).

Eles são particularmente bons para condições como "selecionar todos os registros com um determinado ponto dentro do intervalo do registro", que é exatamente o seu caso.

Você armazena o start_date e end_date como o início e o fim de uma LineString (convertendo-os para UNIX timestamps de outro valor numérico), indexe-os com um SPATIAL indexe e procure por todos esses LineString s cuja caixa delimitadora mínima (MBR ) contém o valor de data em questão, usando MBRContains .

Veja esta entrada no meu blog sobre como fazer isso em MySQL :

e uma breve visão geral do desempenho do SQL Server :

A mesma solução pode ser aplicada para pesquisar um determinado IP contra intervalos de rede armazenados no banco de dados.

Essa tarefa, junto com sua consulta, é outro exemplo de tal condição frequentemente usado.

Simples B-Tree índices não são bons se os intervalos podem se sobrepor.

Se eles não puderem (e você sabe disso), você pode usar a solução brilhante proposta por @AlexKuznetsov

Observe também que o desempenho dessa consulta depende totalmente da distribuição de seus dados.

Se você tiver muitos registros em B e poucos registros em A , você poderia apenas construir um índice em B.dates e deixe o TS/CIS em A vai.

Esta consulta sempre lerá todas as linhas de A e usará Index Seek em B.dates em um loop aninhado.

Se os seus dados forem distribuídos de outra forma, i. e. você tem muitas linhas em A mas poucos em B , e os intervalos geralmente são curtos, você pode redesenhar um pouco suas tabelas:
A

start_date interval_length

, crie um índice composto em A (interval_length, start_date)

e use esta consulta:
SELECT  *
FROM    (
        SELECT  DISTINCT interval_length
        FROM    a
        ) ai
CROSS JOIN
        b
JOIN    a
ON      a.interval_length = ai.interval_length
        AND a.start_date BETWEEN b.date - ai.interval_length AND b.date