Bijwerken:
Zie dit artikel in mijn blog voor een efficiënte indexeringsstrategie voor uw zoekopdracht met behulp van berekende kolommen:
Het belangrijkste idee is dat we gewoon de afgeronde length
. berekenen en startDate
voor u bereiken en zoek ze vervolgens met behulp van gelijkheidsvoorwaarden (die goed zijn voor B-Tree
indexen)
In MySQL
en in SQL Server 2008
je zou SPATIAL
. kunnen gebruiken indexen (R-Tree
).
Ze zijn vooral goed voor de voorwaarden zoals "selecteer alle records met een bepaald punt binnen het bereik van de record", wat precies uw geval is.
Je slaat de start_date
. op en end_date
als het begin en het einde van een LineString
(ze converteren naar UNIX
tijdstempels van een andere numerieke waarde), indexeer ze met een SPATIAL
indexeer en zoek naar al dergelijke LineString
s waarvan het minimale begrenzingsvak (MBR
) bevat de datumwaarde in kwestie, met behulp van MBRContains
.
Zie dit bericht in mijn blog over hoe je dit kunt doen in MySQL
:
en een kort prestatieoverzicht voor SQL Server
:
Dezelfde oplossing kan worden toegepast voor het zoeken naar een bepaald IP
tegen netwerkbereiken die zijn opgeslagen in de database.
Deze taak, samen met uw vraag, is een ander vaak gebruikt voorbeeld van een dergelijke voorwaarde.
Effen B-Tree
indexen zijn niet goed als de bereiken elkaar kunnen overlappen.
Als ze dat niet kunnen (en je weet het), kun je de briljante oplossing gebruiken die wordt voorgesteld door @AlexKuznetsov
Houd er ook rekening mee dat deze queryprestaties volledig afhankelijk zijn van uw gegevensdistributie.
Als u veel records heeft in B
en enkele records in A
, je zou gewoon een index kunnen bouwen op B.dates
en laat de TS/CIS
op A
ga.
Deze zoekopdracht leest altijd alle rijen van A
en zal Index Seek
. gebruiken op B.dates
in een geneste lus.
Als uw gegevens andersom worden verspreid, i. e. je hebt veel rijen in A
maar weinig in B
, en de reeksen zijn over het algemeen kort, dan zou je je tabellen een beetje kunnen herontwerpen:
A
start_date interval_length
, maak een samengestelde index op A (interval_length, start_date)
en gebruik deze vraag:
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