J'ai une table comme celle-ci:
CREATE TABLE Updates
(
UpdateId INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
ObjectId INT NOT NULL
)
Suivi essentiellement des mises à jour des objets avec un ID croissant.
Le consommateur de ce tableau sélectionnera un bloc de 100 ID d'objet distincts, classés par UpdateId
et à partir d'un spécifique UpdateId
. Essentiellement, en gardant une trace de l'endroit où il s'est arrêté, puis en recherchant des mises à jour.
J'ai trouvé cela un problème d'optimisation intéressante parce que je ne l' ai été en mesure de générer un plan de requête au maximum optimale en écrivant des requêtes qui arrivent à faire ce que je veux en raison d'indices, mais ne vous garantis que je veux:
SELECT DISTINCT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
Où @fromUpdateId
est un paramètre de procédure stockée.
Avec un plan de:
SELECT <- TOP <- Hash match (flow distinct, 100 rows touched) <- Index seek
En raison de la recherche sur l' UpdateId
index utilisé, les résultats sont déjà agréables et classés du ID de mise à jour le plus bas au plus élevé comme je le souhaite. Et cela génère un plan de flux distinct , ce que je veux. Mais la commande n'est évidemment pas un comportement garanti, donc je ne veux pas l'utiliser.
Cette astuce entraîne également le même plan de requête (mais avec un TOP redondant):
WITH ids AS
(
SELECT ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
ORDER BY UpdateId OFFSET 0 ROWS
)
SELECT DISTINCT TOP 100 ObjectId FROM ids
Cependant, je ne suis pas sûr (et je ne le pense pas) si cela garantit vraiment la commande.
Voici une requête que j'espérais que SQL Server serait assez intelligent pour simplifier, mais cela finit par générer un très mauvais plan de requête:
SELECT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
GROUP BY ObjectId
ORDER BY MIN(UpdateId)
Avec un plan de:
SELECT <- Top N Sort <- Hash Match aggregate (50,000+ rows touched) <- Index Seek
J'essaie de trouver un moyen de générer un plan optimal avec une recherche d'index UpdateId
et un flux distinct pour supprimer les doublons ObjectId
. Des idées?
Exemple de données si vous le souhaitez. Les objets auront rarement plus d'une mise à jour, et ne devraient presque jamais en avoir plus d'une dans un ensemble de 100 lignes, c'est pourquoi je recherche un flux distinct , à moins qu'il y ait quelque chose de mieux que je ne sache pas? Cependant, il n'y a aucune garantie qu'un seul ObjectId
ne contiendra pas plus de 100 lignes dans le tableau. Le tableau compte plus de 1 000 000 de lignes et devrait croître rapidement.
Supposons que l'utilisateur de ceci ait une autre façon de trouver la suivante appropriée @fromUpdateId
. Pas besoin de le renvoyer dans cette requête.
la source