Aktualizace:
Efektivní strategii indexování pro váš dotaz pomocí vypočítaných sloupců naleznete v tomto článku na mém blogu:
Hlavní myšlenkou je, že pouze počítáme zaokrouhlenou length
a startDate
pro vás rozsahy a poté je vyhledejte pomocí podmínek rovnosti (které jsou dobré pro B-Tree
indexy)
V MySQL
a v SQL Server 2008
můžete použít SPATIAL
indexy (R-Tree
).
Jsou zvláště dobré pro podmínky jako „vyberte všechny záznamy s daným bodem v rozsahu záznamu“, což je jen váš případ.
Uložíte start_date
a end_date
jako začátek a konec LineString
(převést je na UNIX
časová razítka jiné číselné hodnoty), indexujte je pomocí SPATIAL
indexovat a hledat všechny takové LineString
s, jehož minimální ohraničovací rámeček (MBR
) obsahuje příslušnou hodnotu data pomocí MBRContains
.
Podívejte se na tento záznam na mém blogu o tom, jak to udělat v MySQL
:
a stručný přehled výkonu pro SQL Server
:
Stejné řešení lze použít pro vyhledávání dané IP
proti síťovým rozsahům uloženým v databázi.
Tato úloha je spolu s vaším dotazem dalším často používaným příkladem takové podmínky.
Obyčejný B-Tree
indexy nejsou dobré, pokud se rozsahy mohou překrývat.
Pokud nemohou (a vy to víte), můžete použít skvělé řešení navržené @AlexKuznetsov
Všimněte si také, že výkon tohoto dotazu zcela závisí na vaší distribuci dat.
Pokud máte mnoho záznamů v B
a několik záznamů v A
, můžete jednoduše vytvořit index na B.dates
a nechte TS/CIS
na A
jít.
Tento dotaz vždy přečte všechny řádky z A
a použije Index Seek
dne B.dates
ve vnořené smyčce.
Pokud jsou vaše data distribuována jiným způsobem, tj. E. v A
máte spoustu řádků ale málo v B
, a rozsahy jsou obecně krátké, pak byste mohli své tabulky trochu předělat:
A
start_date interval_length
, vytvořte složený index na A (interval_length, start_date)
a použijte tento dotaz:
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