Je gère une base de données SQL Server 2016 où j'ai la table suivante avec 100 lignes de plus de plus de millions:
StationId | ParameterId | DateTime | Value
1 | 2 | 2020-02-04 15:00:000 | 5.20
1 | 2 | 2020-02-04 14:00:000 | 5.20
1 | 2 | 2020-02-04 13:00:000 | 5.20
1 | 3 | 2020-02-04 15:00:000 | 2.81
1 | 3 | 2020-02-04 14:00:000 | 2.81
1 | 4 | 2020-02-04 15:00:000 | 5.23
2 | 2 | 2020-02-04 15:00:000 | 3.70
2 | 4 | 2020-02-04 15:00:000 | 12.20
3 | 2 | 2020-02-04 15:00:000 | 1.10
Cette table a un index en cluster pour StationID, ParameID et DateTime, dans cet ordre, tous ascendants.
Ce dont j'ai besoin, c'est que pour chaque paire unique Stationid - paramétrice, renvoyez la valeur la plus récente de la colonne DateTime:
StationId | ParameterId | LastDate
1 | 2 | 2020-02-04 15:00:000
1 | 3 | 2020-02-04 15:00:000
1 | 4 | 2020-02-04 15:00:000
2 | 2 | 2020-02-04 15:00:000
2 | 4 | 2020-02-04 15:00:000
3 | 2 | 2020-02-04 15:00:000
Ce que je fais maintenant, c'est la requête suivante, qui prend environ 90 à 120 secondes pour courir:
SELECT StationId, ParameterId, MAX(DateTime) AS LastDate
FROM MyTable WITH (NOLOCK)
GROUP BY StationId, ParameterId
J'ai également vu de nombreux postes suggérant ce qui suit, qui prend plus de 10 minutes à courir:
SELECT StationId, ParameterId, DateTime AS LastDate
FROM
(
SELECT StationId, ParameterId, DateTime
,ROW_NUMBER() OVER (PARTITION BY StationId,ParameterIdORDER BY DateTime DESC) as row_num
FROM MyTable WITH (NOLOCK)
)
WHERE row_num = 1
Même dans le meilleur cas (en utilisant le groupe par la clause et la fonction d'agrégation maximale), le plan d'exécution n'indique pas un indice de recherche:
Je me demande s'il y a un meilleur moyen d'effectuer cette requête (ou de construire l'index) afin d'obtenir une meilleure heure d'exécution.
Si vous avez un petit nombre suffisant de paires (stationid, paramétrice), essayez une requête comme celle-ci:
select StationID, ParameterID, m.DateTime LastDate
from StationParameter sp
cross apply
(
select top 1 DateTime
from MyTable
where StationID = sp.StationID
and ParameterID = sp.ParameterID
order by DateTime desc
) m
Pour activer SQL Server d'effectuer une recherche, recherchez le dernier DateTime
pour chaque paire (stationId, paramètre).
Avec seulement un indice en cluster sur (stationId, paramétrice, DateTime), SQL Server découvre les paires distinctes (stationidales, paramétrices) sans balayer le niveau de la feuille de l'index, et il peut trouver la plus grande date d'heure pendant la numérisation.
Aussi à 100 m + lignes, cette table peut être meilleure en tant que colonne en cluster au lieu d'un index en cluster Bree.