Effet de performance de l'utilisation de TOP 1 dans une requête SELECT

J'ai une table d'user où il y a des colonnes de nom d'user et d'application. Le nom d'user peut être répété mais la combinaison Nom d'user + Application est unique, mais je n'ai pas l'set de contraintes unique sur la table (pour la performance)

Question: y aura-t-il une différence (en termes de performance) entre:

SELECT * FROM User where UserName='myuser' AND Application='myapp' 

ET –

 SELECT TOP 1 * FROM User where UserName='myuser' AND Application='myapp' 

Comme la combinaison Nom d'user + Application est unique, les deux requêtes renverront toujours pas plus d'un logging, donc TOP 1 n'affecte pas le résultat. J'ai toujours pensé que l'ajout de TOP 1 accélèrerait vraiment les choses car SQL Server ne findait plus de correspondance, mais j'ai récemment lu dans un article que l'utilisation de TOP ralentirait les choses et il est recommandé d'éviter, même si elles n'ont pas expliqué pourquoi.

Des commentaires?

Je vous remercie! Andrey

Vous pouvez get une différence de performance en utilisant simplement le top , mais la vraie performance que vous obtenez en utilisant des index.

Si vous avez un index pour les champs UserName et Application, la database n'a même pas besoin de toucher la table tant qu'elle n'a pas isolé le seul logging. De plus, il sait déjà à partir des statistics de la table que les valeurs sont uniques, donc utiliser top ne fait aucune différence.

S'il y a plus d'une ligne dans les résultats et aucune clause ORDER BY, le «TOP 1» économise une tonne de travail pour le server. S'il y a une clause order by, le server doit toujours matérialiser l'set des résultats, et s'il n'y a qu'une seule ligne, cela ne change rien.

Je pense que cela dépend du plan d'exécution des requêtes que génère SQL … Dans le passé, sur les versions précédentes de SQL Server, l'utilisation d'un 'TOP' superflus offrait des avantages de performances avec des requêtes complexes avec de nombreuses jointures. Mais certainement pas dans tous les cas.

Je suppose que le meilleur conseil que je peux donner est de l'essayer au cas par cas.

vous dites que vous n'appliquez pas la contrainte, cela signifie qu'il n'y a pas d'index unique sur (UserName, Application) ou (Application, UserName). La requête peut-elle utiliser un path d'access qui search soit sur UserName soit sur Application ? En d'autres termes, l'une de ces deux colonnes est-elle indexée? Si oui, alors le plan choisira le plus sélectif qui est indexé et fait un balayage de gamme, éventuellement une boucle nestede avec une search de signet si l'index est non-groupé, puis un filter. Top 1 arrête la requête après la correspondance du premier filter, mais si cela fait une différence dépend de la cardinalité des données (combien d'loggings trouve l'parsing de plage et combien satisfont le filter).

S'il n'y a pas d'index, il effectuera un scan en cluster complet, quoi qu'il arrive. Top 1 arrête l'parsing au premier match, que ce soit après le traitement de 1 logging ou après le traitement de 999 mil. loggings depdends sur le nom d'user et l'application réels …

La seule chose qui fera une réelle différence est de permettre à la requête de searchr les deux valeurs, ie. avoir un indice de couverture. La contrainte serait imposée à travers exactement un tel indice de couverture. En d'autres termes: en désactivant la contrainte, probablement pour la performance en écriture, soyez prêt à payer le prix en lecture. Est-ce important? Avez-vous effectué des mesures pour confirmer que l'écriture d'index supplémentaire de la contrainte réduirait considérablement la performance?