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