Lorsque vous utilisez une sous-requête pour trouver le nombre total de tous les enregistrements précédents avec un champ correspondant, les performances sont terribles sur une table avec aussi peu que 50 000 enregistrements. Sans la sous-requête, la requête s'exécute en quelques millisecondes. Avec la sous-requête, le temps d'exécution est supérieur à une minute.
Pour cette requête, le résultat doit:
- N'incluez que les enregistrements dans une plage de dates donnée.
- Incluez un décompte de tous les enregistrements antérieurs, sans compter l'enregistrement en cours, quelle que soit la plage de dates.
Schéma de table de base
Activity
======================
Id int Identifier
Address varchar(25)
ActionDate datetime2
Process varchar(50)
-- 7 other columns
Exemples de données
Id Address ActionDate (Time part excluded for simplicity)
===========================
99 000 2017-05-30
98 111 2017-05-30
97 000 2017-05-29
96 000 2017-05-28
95 111 2017-05-19
94 222 2017-05-30
Résultats attendus
Pour la plage de dates de 2017-05-29
à2017-05-30
Id Address ActionDate PriorCount
=========================================
99 000 2017-05-30 2 (3 total, 2 prior to ActionDate)
98 111 2017-05-30 1 (2 total, 1 prior to ActionDate)
94 222 2017-05-30 0 (1 total, 0 prior to ActionDate)
97 000 2017-05-29 1 (3 total, 1 prior to ActionDate)
Les enregistrements 96 et 95 sont exclus du résultat, mais sont inclus dans la PriorCount
sous - requête
Requête actuelle
select
*.a
, ( select count(*)
from Activity
where
Activity.Address = a.Address
and Activity.ActionDate < a.ActionDate
) as PriorCount
from Activity a
where a.ActionDate between '2017-05-29' and '2017-05-30'
order by a.ActionDate desc
Indice actuel
CREATE NONCLUSTERED INDEX [IDX_my_nme] ON [dbo].[Activity]
(
[ActionDate] ASC
)
INCLUDE ([Address]) WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
DROP_EXISTING = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
)
Question
- Quelles stratégies pourraient être utilisées pour améliorer les performances de cette requête?
Edit 1
En réponse à la question de ce que je peux modifier sur la base de données: je peux modifier les index, mais pas la structure de la table.
Edit 2
J'ai maintenant ajouté un index de base sur la Address
colonne, mais cela ne semble pas beaucoup s'améliorer. Je trouve actuellement de bien meilleures performances en créant une table temporaire et en insérant les valeurs sans le PriorCount
puis en mettant à jour chaque ligne avec leurs nombres spécifiques.
Edit 3
La bobine d'index Joe Obbish (réponse acceptée) trouvée était le problème. Une fois que j'en ai ajouté un nouveau nonclustered index [xyz] on [Activity] (Address) include (ActionDate)
, les temps de requête sont passés de plus d'une minute à moins d'une seconde sans utiliser de table temporaire (voir éditer 2).
nonclustered index [xyz] on [Activity] (Address) include (ActionDate)
, les temps de requête sont passés de plus d'une minute à moins d'une seconde. +10 si je pouvais. Merci!