Je suis simplement curieux de savoir pourquoi une requête agrégée s'exécute tellement plus rapidement avec une GROUP BY
clause que sans.
Par exemple, l'exécution de cette requête prend près de 10 secondes
SELECT MIN(CreatedDate)
FROM MyTable
WHERE SomeIndexedValue = 1
Alors que celui-ci prend moins d'une seconde
SELECT MIN(CreatedDate)
FROM MyTable
WHERE SomeIndexedValue = 1
GROUP BY CreatedDate
Il n'y en a qu'un CreatedDate
dans ce cas, la requête groupée renvoie donc les mêmes résultats que la requête non groupée.
J'ai remarqué que les plans d'exécution des deux requêtes sont différents - La deuxième requête utilise le parallélisme alors que la première ne le fait pas.
Est-il normal que SQL Server évalue une requête agrégée différemment s'il n'a pas de clause GROUP BY? Et puis-je faire quelque chose pour améliorer les performances de la première requête sans utiliser de GROUP BY
clause?
Éditer
Je viens d'apprendre que je peux utiliser OPTION(querytraceon 8649)
pour définir les frais généraux du parallélisme à 0, ce qui oblige la requête à utiliser un certain parallélisme et réduit le temps d'exécution à 2 secondes, bien que je ne sache pas s'il y a des inconvénients à utiliser cet indice de requête.
SELECT MIN(CreatedDate)
FROM MyTable
WHERE SomeIndexedValue = 1
OPTION(querytraceon 8649)
Je préférerais toujours un temps d'exécution plus court car la requête est destinée à remplir une valeur lors de la sélection de l'utilisateur, donc devrait idéalement être instantanée comme la requête groupée. En ce moment, je suis juste en train de terminer ma requête, mais je sais que ce n'est pas vraiment une solution idéale.
SELECT Min(CreatedDate)
FROM
(
SELECT Min(CreatedDate) as CreatedDate
FROM MyTable WITH (NOLOCK)
WHERE SomeIndexedValue = 1
GROUP BY CreatedDate
) as T
Éditer # 2
En réponse à la demande de Martin pour plus d'informations :
Les deux CreatedDate
et SomeIndexedValue
ont un index non unique et non cluster séparé sur eux. SomeIndexedValue
est en fait un champ varchar (7), même s'il stocke une valeur numérique qui pointe vers le PK (int) d'une autre table. La relation entre les deux tables n'est pas définie dans la base de données. Je ne suis pas du tout censé changer la base de données et je ne peux écrire que des requêtes qui interrogent des données.
MyTable
contient plus de 3 millions d'enregistrements, et à chaque enregistrement est affecté un groupe auquel il appartient ( SomeIndexedValue
). Les groupes peuvent contenir de 1 à 200 000 enregistrements
MAXDOP
définit le degré maximal de parallélisme, ce qui limite le nombre de processeurs que la requête peut utiliser. Cela rendrait la deuxième requête aussi lente que la première, car elle supprime ses capacités à utiliser le parallélisme, ce qui n'est pas ce que je veux.