Database
 sql >> Base de données >  >> RDS >> Database

Surprises et hypothèses de performance :SET NOCOUNT ON

Si vous avez déjà utilisé Management Studio, ce message de sortie vous semblera probablement familier :

(1 rangée(s) concernée(s))

Cela provient de DONE_IN_PROC de SQL Server message, qui est envoyé à la fin de toute instruction SQL ayant renvoyé un résultat (y compris la récupération d'un plan d'exécution, c'est pourquoi vous voyez deux de ces messages alors que vous n'avez exécuté qu'une seule requête).

Vous pouvez supprimer ces messages avec la commande suivante :

SET NOCOUNT ON;

Pourquoi ferais-tu ça? Parce que ces messages sont bavards et souvent inutile . Dans mes présentations sur les mauvaises habitudes et les meilleures pratiques, je parle souvent de l'ajout de SET NOCOUNT ON; à toutes les procédures stockées et en l'activant dans le code d'application qui soumet des requêtes ad hoc. (Pendant le débogage, cependant, vous souhaiterez peut-être qu'un indicateur réactive les messages, car la sortie peut être utile dans ces cas.)

J'ai toujours ajouté la clause de non-responsabilité selon laquelle le conseil d'activer cette option partout n'est pas universel ; ça dépend. Les jeux d'enregistrements ADO de la vieille école les interprétaient en fait comme des jeux de résultats, donc les ajouter aux requêtes après coup pourrait en fait casser les applications qui les ignorent déjà manuellement. Et certains ORM (tousse NHibernate toux ) analysent en fait les résultats pour déterminer le succès des commandes DML (pouah !). Veuillez tester vos modifications.

Je sais qu'à un moment donné, je m'étais prouvé que ces messages bavards pouvaient avoir un impact sur les performances, en particulier sur un réseau lent. Mais ça fait longtemps, et la semaine dernière, Erin Stellato m'a demandé si je l'avais déjà officiellement documenté. Je ne l'ai pas fait, alors voilà. Nous allons prendre une boucle très simple, où nous mettrons à jour une variable de table un million de fois :

SET NOCOUNT OFF;
 
DECLARE @i INT = 1;
DECLARE @x TABLE(a INT);
INSERT @x(a) VALUES(1);
 
SELECT SYSDATETIME();
 
WHILE @i < 1000000
BEGIN
  UPDATE @x SET a = 1;
  SET @i += 1;
END
 
SELECT SYSDATETIME();

Vous remarquerez peut-être deux choses :

  • Le volet des messages est inondé d'instances de (1 row(s) affected) message:

  • Le SELECT SYSDATETIME(); initial ne s'affiche pas dans le volet des résultats tant que le lot complet n'est pas terminé. C'est à cause des inondations.
  • Ce lot a pris environ 21 secondes pour s'exécuter.

Maintenant, répétons cela sans le DONE_IN_PROC messages, en changeant SET NOCOUNT OFF; à SET NOCOUNT ON; et relancez-le.

Alors que le volet des messages n'était plus inondé de messages affectés par les lignes, le lot prenait encore environ 21 secondes pour s'exécuter.

Puis j'ai pensé, attendez une seconde, je sais ce qui se passe. Je suis sur une machine locale, sans réseau impliqué, en utilisant la mémoire partagée, je n'ai que du SSD et des tas et des tas de RAM…

J'ai donc répété les tests en utilisant ma copie locale de SSMS par rapport à une base de données Azure SQL distante - un Standard, S0, V12. Cette fois, les requêtes ont pris beaucoup plus de temps, même après avoir réduit les itérations de 1 000 000 à 100 000. Mais encore une fois, il n'y avait aucune différence tangible dans les performances si DONE_IN_PROC messages ont été envoyés ou non. Les deux lots ont pris environ 104 secondes, ce qui était reproductible sur de nombreuses itérations.

Conclusion

Pendant des années, j'avais l'impression que SET NOCOUNT ON; était un élément essentiel de toute stratégie de performance. Cela était basé sur des observations que j'avais faites à une époque sans doute différente, et qui sont moins susceptibles de se manifester aujourd'hui.

Cela dit, je continuerai à utiliser SET NOCOUNT ON , même si sur le matériel d'aujourd'hui, il n'y a pas de différence notable de performances. Je suis toujours très attaché à la réduction du trafic réseau dans la mesure du possible. Je devrais envisager de mettre en œuvre un test où j'ai une bande passante beaucoup plus limitée (peut-être que quelqu'un a un CD AOL qu'il peut me prêter ?), Ou avoir une machine où la quantité de mémoire est inférieure aux limites de la mémoire tampon de sortie de Management Studio, pour être sûr qu'il y a n'est pas un impact potentiel dans les pires scénarios. En attendant, même si cela ne change pas les performances perçues de votre application, cela peut toujours aider votre portefeuille à toujours activer cette option définie, en particulier dans des situations comme Azure, où vous pouvez être facturé pour le trafic de sortie.