Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Moyen le plus rapide pour cette requête (quelle est la meilleure stratégie) étant donné une plage de dates

Mise à jour :

Consultez cet article sur mon blog pour une stratégie d'indexation efficace pour votre requête à l'aide de colonnes calculées :

L'idée principale est que nous calculons simplement la length arrondie et startDate pour vos plages, puis recherchez-les en utilisant des conditions d'égalité (qui sont bonnes pour B-Tree index)

En MySQL et dans SQL Server 2008 vous pouvez utiliser SPATIAL index (R-Tree ).

Ils sont particulièrement adaptés aux conditions telles que "sélectionner tous les enregistrements avec un point donné à l'intérieur de la plage d'enregistrements", ce qui est votre cas.

Vous stockez la start_date et end_date comme début et fin d'un LineString (en les convertissant en UNIX horodatages d'une autre valeur numérique), indexez-les avec un SPATIAL indexer et rechercher tous ces LineString s dont la boîte englobante minimale (MBR ) contient la valeur de date en question, en utilisant MBRContains .

Voir cette entrée dans mon blog sur la façon de faire cela dans MySQL :

et un bref aperçu des performances de SQL Server :

La même solution peut être appliquée pour rechercher un IP donné par rapport aux plages de réseau stockées dans la base de données.

Cette tâche, ainsi que votre requête, est un autre exemple souvent utilisé d'une telle condition.

B-Tree ordinaire les index ne sont pas bons si les plages peuvent se chevaucher.

S'ils ne le peuvent pas (et vous le savez), vous pouvez utiliser la solution géniale proposée par @AlexKuznetsov

Notez également que les performances de cette requête dépendent totalement de la distribution de vos données.

Si vous avez beaucoup d'enregistrements dans B et quelques enregistrements en A , vous pouvez simplement créer un index sur B.dates et laissez le TS/CIS sur A allez.

Cette requête lira toujours toutes les lignes de A et utilisera Index Seek le B.dates dans une boucle imbriquée.

Si vos données sont distribuées dans l'autre sens, i. e. vous avez beaucoup de lignes dans A mais peu en B , et que les plages sont généralement courtes, vous pourriez alors repenser un peu vos tableaux :

A

start_date interval_length

, créer un index composite sur A (interval_length, start_date)

et utilisez cette requête :

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