Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Der schnellste Weg für diese Abfrage (Was ist die beste Strategie) bei gegebenem Datumsbereich

Aktualisierung:

Siehe diesen Artikel in meinem Blog für eine effiziente Indizierungsstrategie für Ihre Abfrage mit berechneten Spalten:

Die Hauptidee ist, dass wir einfach die gerundete length berechnen und startDate für Ihre Bereiche und suchen Sie sie dann unter Verwendung von Gleichheitsbedingungen (die gut für B-Tree sind Indizes)

In MySQL und in SQL Server 2008 Sie könnten SPATIAL verwenden Indizes (R-Tree ).

Sie eignen sich besonders gut für Bedingungen wie "Alle Datensätze mit einem bestimmten Punkt innerhalb des Datensatzbereichs auswählen", was genau Ihr Fall ist.

Sie hinterlegen das start_date und end_date als Anfang und Ende eines LineString (Konvertieren in UNIX Zeitstempel eines anderen numerischen Werts), indizieren Sie sie mit einem SPATIAL indexieren und nach allen solchen LineString suchen s, deren minimaler Begrenzungsrahmen (MBR ) enthält den fraglichen Datumswert mithilfe von MBRContains .

Siehe diesen Eintrag in meinem Blog, wie man das in MySQL macht :

und eine kurze Leistungsübersicht für SQL Server :

Die gleiche Lösung kann für die Suche nach einem bestimmten IP angewendet werden gegen in der Datenbank gespeicherte Netzwerkbereiche.

Diese Aufgabe ist zusammen mit Ihrer Abfrage ein weiteres häufig verwendetes Beispiel für eine solche Bedingung.

Einfacher B-Tree Indizes sind nicht gut, wenn sich die Bereiche überschneiden können.

Wenn dies nicht möglich ist (und Sie wissen es), können Sie die brillante Lösung verwenden, die von @AlexKuznetsov vorgeschlagen wird

Beachten Sie auch, dass diese Abfrageleistung vollständig von Ihrer Datenverteilung abhängt.

Wenn Sie viele Datensätze in B haben und wenige Aufzeichnungen in A , könnten Sie einfach einen Index für B.dates erstellen und lassen Sie den TS/CIS auf A gehen.

Diese Abfrage liest immer alle Zeilen von A und verwendet Index Seek am B.dates in einer verschachtelten Schleife.

Werden Ihre Daten andersherum weitergegeben, d.h. e. Sie haben viele Zeilen in A aber wenige in B , und die Bereiche im Allgemeinen kurz sind, dann könnten Sie Ihre Tabellen ein wenig umgestalten:

A

start_date interval_length

, erstellen Sie einen zusammengesetzten Index für A (interval_length, start_date)

und verwenden Sie diese Abfrage:

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