Aktualizacja:
Zobacz ten artykuł na moim blogu, aby zapoznać się z wydajną strategią indeksowania zapytania przy użyciu kolumn obliczanych:
Główną ideą jest to, że po prostu obliczamy zaokrągloną length i startDate dla ciebie zakresów, a następnie wyszukaj je używając warunków równości (które są dobre dla B-Tree indeksy)
W MySQL oraz w SQL Server 2008 możesz użyć SPATIAL indeksy (R-Tree ).
Są one szczególnie dobre w warunkach takich jak „wybierz wszystkie rekordy z danym punktem w zakresie rekordu”, co jest właśnie w Twoim przypadku.
Przechowujesz start_date i end_date jako początek i koniec LineString (konwertując je do UNIX znaczniki czasu innej wartości liczbowej), zaindeksuj je za pomocą SPATIAL indeksuj i szukaj wszystkich takich LineString s którego minimalne pole ograniczające (MBR ) zawiera kwestionowaną wartość daty, używając MBRContains .
Zobacz ten wpis na moim blogu, jak to zrobić w MySQL :
i krótki przegląd wydajności dla SQL Server :
To samo rozwiązanie można zastosować do wyszukiwania podanego IP z zakresami sieci przechowywanymi w bazie danych.
To zadanie, wraz z zapytaniem, jest kolejnym często używanym przykładem takiego warunku.
Zwykłe B-Tree indeksy nie są dobre, jeśli zakresy mogą się nakładać.
Jeśli nie mogą (a wiesz o tym), możesz skorzystać z genialnego rozwiązania zaproponowanego przez @AlexKuznetsov
Pamiętaj również, że wydajność tego zapytania całkowicie zależy od dystrybucji danych.
Jeśli masz dużo rekordów w B i kilka rekordów w A , możesz po prostu zbudować indeks na B.dates i niech TS/CIS na A idź.
To zapytanie zawsze odczyta wszystkie wiersze z A i użyje Index Seek w B.dates w zagnieżdżonej pętli.
Jeśli Twoje dane są dystrybuowane w odwrotny sposób, to znaczy. mi. masz dużo wierszy w A ale niewiele w B , a zakresy są zazwyczaj krótkie, możesz trochę przeprojektować swoje tabele:
A
start_date interval_length
, utwórz indeks złożony na A (interval_length, start_date)
i użyj tego zapytania:
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