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