Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Il modo più veloce per questa query (qual è la strategia migliore) dato un intervallo di date

Aggiornamento:

Vedi questo articolo nel mio blog per una strategia di indicizzazione efficiente per la tua query utilizzando colonne calcolate:

L'idea principale è che calcoliamo semplicemente la length arrotondata e startDate per te intervalli e quindi cercali utilizzando condizioni di uguaglianza (che sono buone per B-Tree indici)

In MySQL e in SQL Server 2008 potresti usare SPATIAL indici (R-Tree ).

Sono particolarmente utili per condizioni come "seleziona tutti i record con un determinato punto all'interno dell'intervallo del record", che è proprio il tuo caso.

Memorizzi il start_date e end_date come inizio e fine di una LineString (convertendoli in UNIX timestamp di un altro valore numerico), indicizzarli con un SPATIAL indicizza e cerca tutti questi LineString s il cui riquadro di delimitazione minimo (MBR ) contiene il valore della data in questione, utilizzando MBRContains .

Vedi questa voce nel mio blog su come farlo in MySQL :

e una breve panoramica delle prestazioni per SQL Server :

La stessa soluzione può essere applicata per la ricerca di un dato IP rispetto agli intervalli di rete archiviati nel database.

Questa attività, insieme alla tua query, è un altro esempio usato spesso di tale condizione.

B-Tree semplice gli indici non vanno bene se gli intervalli possono sovrapporsi.

Se non possono (e tu lo sai), puoi utilizzare la brillante soluzione proposta da @AlexKuznetsov

Tieni inoltre presente che le prestazioni di questa query dipendono totalmente dalla distribuzione dei dati.

Se hai molti record in B e pochi record in A , potresti semplicemente creare un indice su B.dates e lascia che il TS/CIS su A vai.

Questa query leggerà sempre tutte le righe da A e utilizzerà Index Seek su B.dates in un ciclo annidato.

Se i tuoi dati sono distribuiti in modo diverso, i. e. hai molte righe in A ma pochi in B , e gli intervalli sono generalmente brevi, puoi riprogettare un po' le tue tabelle:

A

start_date interval_length

, crea un indice composito su A (interval_length, start_date)

e usa questa query:

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