Inspiré par cette question où les avis divergent sur SET NOCOUNT ...
Devrions-nous utiliser SET NOCOUNT ON pour SQL Server? Sinon, pourquoi pas?
What it does Edit 6, le 22 juillet 2011
Il supprime le message "xx lignes affectées" après tout DML. Il s'agit d'un jeu de résultats et une fois envoyé, le client doit le traiter. C'est minuscule, mais mesurable (voir les réponses ci-dessous)
Pour les déclencheurs, etc., le client recevra plusieurs "xx lignes affectées", ce qui provoque toutes sortes d'erreurs pour certains ORM, MS Access, JPA, etc. (voir les modifications ci-dessous)
Contexte:
La meilleure pratique généralement acceptée (je pensais jusqu'à cette question) est d'utiliser SET NOCOUNT ON
dans les déclencheurs et les procédures stockées dans SQL Server. Nous l'utilisons partout et un rapide google montre que de nombreux MVP SQL Server sont également d'accord.
MSDN indique que cela peut casser un .net SQLDataAdapter .
Maintenant, cela signifie pour moi que le SQLDataAdapter est limité au traitement CRUD tout simplement parce qu'il s'attend à ce que le message "n lignes affectées" corresponde. Donc, je ne peux pas utiliser:
- SI EXISTE pour éviter les doublons (aucune ligne affectée au message) Remarque: à utiliser avec prudence
- O NOT IL N'EXISTE PAS (moins de lignes que prévu
- Filtrer les mises à jour triviales (par exemple, aucune donnée ne change réellement)
- Faites tout accès à la table avant (comme la journalisation)
- Masquer la complexité ou la dénormalisation
- etc
Dans la question marc_s (qui connaît ses trucs SQL) dit de ne pas l'utiliser. Cela diffère de ce que je pense (et je me considère comme quelque peu compétent en SQL aussi).
Il est possible que je manque quelque chose (n'hésitez pas à souligner l'évidence), mais qu'en pensez-vous?
Remarque: cela fait des années que je n'ai pas vu cette erreur car je n'utilise pas SQLDataAdapter de nos jours.
Modifications après commentaires et questions:
Edit: Plus de réflexions ...
Nous avons plusieurs clients: l'un peut utiliser un C # SQLDataAdaptor, un autre peut utiliser nHibernate de Java. Celles-ci peuvent être affectées de différentes manières avec SET NOCOUNT ON
.
Si vous considérez les proc stockés comme des méthodes, alors c'est une mauvaise forme (anti-modèle) de supposer que certains traitements internes fonctionnent d'une certaine manière pour vos propres besoins.
Edit 2: un déclencheur brisant la question nHibernate , où SET NOCOUNT ON
ne peut pas être défini
(et non, ce n'est pas un doublon de cela )
Edit 3: Encore plus d'informations, grâce à mon collègue MVP
- KB 240882 , problème provoquant des déconnexions sur SQL 2000 et versions antérieures
- Démo du gain de performance
Edit 4: 13 mai 2011
Interrompt également Linq 2 SQL lorsqu'il n'est pas spécifié?
Edit 5: 14 juin 2011
Interrompt JPA, proc stocké avec des variables de table: JPA 2.0 prend-il en charge les variables de table SQL Server?
Edit 6: 15 août 2011
La grille de données SSMS "Modifier les lignes" nécessite SET NOCOUNT ON: Mettre à jour le déclencheur avec GROUP BY
Edit 7: 07 mars 2013
Détails plus approfondis de @RemusRusanu:
SET NOCOUNT ON fait-il vraiment une différence de performance
Réponses:
Ok maintenant j'ai fait mes recherches, voici l'affaire:
Dans le protocole TDS,
SET NOCOUNT ON
enregistre uniquement 9 octets par requête tandis que le texte "SET NOCOUNT ON" lui-même est un énorme 14 octets. Je pensais que cela123 row(s) affected
était retourné du serveur en texte brut dans un paquet réseau séparé, mais ce n'est pas le cas. Il s'agit en fait d'une petite structure appeléeDONE_IN_PROC
intégrée dans la réponse. Ce n'est pas un paquet réseau séparé, donc aucun aller-retour n'est gaspillé.Je pense que vous pouvez vous en tenir au comportement de comptage par défaut presque toujours sans vous soucier des performances. Il existe cependant des cas où le calcul du nombre de lignes à l'avance aurait un impact sur les performances, comme un curseur en avant uniquement. Dans ce cas, NOCOUNT pourrait être une nécessité. En dehors de cela, il n'est absolument pas nécessaire de suivre la devise "utiliser NOCOUNT dans la mesure du possible".
Voici une analyse très détaillée de l'insignifiance du
SET NOCOUNT
paramètre: http://daleburnett.com/2014/01/everything-ever-wanted-know-set-nocount/la source
DONINPROC
LeDONE
message (RPC) ou (BATCH) est diffusé avec l'rowcount
ensemble des lignes affectées, tandis que l'done_count
indicateur l'esttrue
, peu importe s'il l'NO_COUNT
estON
. Dépend de l'implémentation de la bibliothèque cliente dans les cas où la requête contient des instructions SELECT ou des appels RPC qui sélectionnent, il peut être nécessaire de désactiver le comptage ... QUAND désactivé, les lignes sont toujours comptées pour l'instruction select, mais l'indicateurDONE_COUNT
est défini surfalse
. Lisez toujours ce que votre bibliothèque client suggère car il interprètera le flux de jetons (message) à votre placeIl m'a fallu beaucoup de fouilles pour trouver de vrais chiffres de référence autour de NOCOUNT, alors j'ai pensé que je partagerais un bref résumé.
la source
SET NOCOUNT OFF;
et c'est pourquoi ils pensent qu'ils n'obtiennent pas d'octets supplémentaires en réponse. Une référence précise serait d'utiliserSET NOCOUNT ON
dans laSET NOCOUNT OFF
procédure stockée à gauche et à droite. De cette façon, vous obtiendrez le package TDS avecDONEINPROC (SET NOCOUNT ...)
, dix à nouveauDONEINPROC (INSERT statement)
, puisRETURNVALUE(@@ROWCOUNT)
, puisRETURNSTATUS 0
pour sp et enfinDONPROC
. L'erreur est là car le deuxième sp n'a pas SET NOCOUNT OFF dans le corps!Lorsque SET NOCOUNT est activé, le nombre (indiquant le nombre de lignes affectées par une instruction Transact-SQL) n'est pas renvoyé. Lorsque SET NOCOUNT est OFF, le compte est renvoyé. Il est utilisé avec n'importe quelle instruction SELECT, INSERT, UPDATE, DELETE.
Le paramètre SET NOCOUNT est défini au moment de l'exécution ou de l'exécution et non au moment de l'analyse.
SET NOCOUNT ON améliore les performances des procédures stockées (SP).
Syntaxe: SET NOCOUNT {ON | OFF}
Exemple de SET NOCOUNT ON:
Exemple de SET NOCOUNT OFF:
la source
Je suppose que dans une certaine mesure, c'est un problème entre DBA et développeur.
En tant que développeur, je dirais de ne pas l'utiliser à moins que vous ne deviez absolument le faire - car l'utiliser peut casser votre code ADO.NET (comme documenté par Microsoft).
Et je suppose qu'en tant que DBA, vous seriez plus de l'autre côté - utilisez-le autant que possible, sauf si vous devez vraiment empêcher son utilisation.
De plus, si vos développeurs utilisent jamais le "RecordsAffected" renvoyé par l'
ExecuteNonQuery
appel de méthode d'ADO.NET , vous avez des problèmes si tout le monde utiliseSET NOCOUNT ON
car dans ce cas, ExecuteNonQuery retournera toujours 0.Consultez également le blog de Peter Bromberg et vérifiez sa position.
Donc, cela se résume vraiment à qui peut fixer les normes :-)
Marc
la source
Si vous dites que vous pourriez également avoir des clients différents, il y a des problèmes avec ADO classique si SET NOCOUNT n'est pas activé.
Un que je rencontre régulièrement: si une procédure stockée exécute un certain nombre d'instructions (et donc un certain nombre de messages "xxx lignes affectées" sont renvoyés), ADO ne semble pas gérer cela et génère l'erreur "Impossible de modifier la propriété ActiveConnection d'un objet Recordset qui a un objet Command comme source. "
Je préconise donc généralement de l'activer, sauf s'il existe une très bonne raison de ne pas le faire. vous avez peut-être trouvé la très bonne raison que je dois approfondir.
la source
Au risque de compliquer les choses, j'encourage une règle légèrement différente de toutes celles que je vois ci-dessus:
NOCOUNT ON
au - dessus d'un proc, avant de faire des travaux dans le proc, mais aussi toujours àSET NOCOUNT OFF
nouveau, avant de retourner les enregistrements de la procédure stockée.Donc, "gardez généralement nocount activé, sauf lorsque vous retournez réellement un jeu de résultats". Je ne sais pas comment cela peut casser n'importe quel code client, cela signifie que le code client n'a jamais besoin de savoir quoi que ce soit sur les processus internes, et ce n'est pas particulièrement onéreux.
la source
En ce qui concerne les déclencheurs brisant NHibernate, j'ai eu cette expérience de première main. Fondamentalement, lorsque NH effectue une MISE À JOUR, il attend un certain nombre de lignes affectées. En ajoutant SET NOCOUNT ON aux déclencheurs, vous obtenez le nombre de lignes à ce que NH attendait, ce qui résout le problème. Alors oui, je recommanderais certainement de le désactiver pour les déclencheurs si vous utilisez NH.
En ce qui concerne l'utilisation dans les SP, c'est une question de préférence personnelle. J'avais toujours désactivé le décompte des lignes, mais là encore, il n'y a pas vraiment d'arguments solides dans les deux cas.
Sur une note différente, vous devriez vraiment envisager de vous éloigner de l'architecture basée sur SP, alors vous n'aurez même pas cette question.
la source
Je voulais vérifier moi-même que «SET NOCOUNT ON» ne sauvegarde pas un paquet réseau ni un aller-retour
J'ai utilisé un test SQLServer 2017 sur un autre hôte (j'ai utilisé une VM)
create table ttable1 (n int); insert into ttable1 values (1),(2),(3),(4),(5),(6),(7) go
create procedure procNoCount as begin set nocount on update ttable1 set n=10-n end
create procedure procNormal as begin update ttable1 set n=10-n end
Puis j'ai tracé des paquets sur le port 1433 avec l'outil 'Wireshark': bouton 'capture filter' -> 'port 1433'exec procNoCount
c'est le paquet de réponse:
0000 00 50 56 c0 00 08 00 0c 29 31 3f 75 08 00 45 00 0010 00 42 d0 ce 40 00 40 06 84 0d c0 a8 32 88 c0 a8 0020 32 01 05 99 fe a5 91 49 e5 9c be fb 85 01 50 18 0030 02 b4 e6 0e 00 00 04 01 00 1a 00 35 01 00 79 00 0040 00 00 00 fe 00 00 e0 00 00 00 00 00 00 00 00 00
exec procNormal
c'est le paquet de réponse:
0000 00 50 56 c0 00 08 00 0c 29 31 3f 75 08 00 45 00 0010 00 4f d0 ea 40 00 40 06 83 e4 c0 a8 32 88 c0 a8 0020 32 01 05 99 fe a5 91 49 e8 b1 be fb 8a 35 50 18 0030 03 02 e6 1b 00 00 04 01 00 27 00 35 01 00 ff 11 0040 00 c5 00 07 00 00 00 00 00 00 00 79 00 00 00 00 0050 fe 00 00 e0 00 00 00 00 00 00 00 00 00
À la ligne 40, je peux voir «07», qui est le nombre de «lignes affectées». Il est inclus dans le paquet de réponse. Aucun paquet supplémentaire.
Il a cependant 13 octets supplémentaires qui pourraient être enregistrés, mais cela ne vaut probablement pas mieux que de réduire les noms de colonnes (par exemple, "ManagingDepartment" en "MD")
Je ne vois donc aucune raison de l'utiliser pour la performance
MAIS Comme d'autres l'ont mentionné, cela peut casser ADO.NET et j'ai également rencontré un problème en utilisant python: MSSQL2008 - Pyodbc - Le SQL précédent n'était pas une requête
Alors probablement une bonne habitude ...
la source
Cette ligne de code est utilisée en SQL pour ne pas renvoyer le nombre de lignes affectées lors de l'exécution de la requête. Si nous n'avons pas besoin du nombre de lignes affectées, nous pouvons l'utiliser car cela aiderait à économiser l'utilisation de la mémoire et augmenterait la vitesse d'exécution de la requête.
la source
ACTIVER NOCOUNT; Le code ci-dessus arrêtera le message généré par le moteur de serveur SQL dans la fenêtre de résultats frontale après l'exécution de la commande DML / DDL.
Pourquoi on le fait? Comme le moteur de serveur SQL prend des ressources pour obtenir l'état et générer le message, il est considéré comme une surcharge du moteur de serveur SQL. Nous activons donc le message non compté.
la source
Un endroit qui
SET NOCOUNT ON
peut vraiment aider est l'endroit où vous effectuez des requêtes dans une boucle ou un curseur. Cela peut représenter beaucoup de trafic réseau.Activer les statistiques client dans SSMS, une exécution de
EXEC NoCountOn
etEXEC NoCountOff
montre qu'il y avait un trafic supplémentaire de 390 Ko sur celui NoCountOff:Probablement pas idéal pour faire des requêtes en boucle ou en curseur, mais nous ne vivons pas non plus dans un monde idéal :)
la source
Je sais que c'est une assez vieille question. mais juste pour la mise à jour.
La meilleure façon d'utiliser "SET NOCOUNT ON" est de le mettre en tant que première instruction dans votre SP et de le désactiver à nouveau juste avant la dernière instruction SELECT.
la source
SET NOCOUNT ON permet même d'accéder aux lignes affectées comme ceci:
Résultats
messages
la source
Je ne sais pas comment tester SET NOCOUNT ON entre le client et SQL, j'ai donc testé un comportement similaire pour une autre commande SET "SET TRANSACTION ISOLATION LEVEL READ UNCIMMITTED"
J'ai envoyé une commande à partir de ma connexion en modifiant le comportement par défaut de SQL (READ COMMITTED), et elle a été modifiée pour les commandes suivantes. Lorsque j'ai changé le niveau d'ISOLATION dans une procédure stockée, cela n'a pas changé le comportement de connexion pour la commande suivante.
Conclusion actuelle,
Je pense que cela concerne d'autres commandes SET telles que "SET NOCOUNT ON"
la source
NOCOUNT
if (pas de décompte == off)
{alors il conservera des données sur le nombre d'enregistrements affectés, donc réduisez les performances} else {il ne suivra pas l'enregistrement des modifications, améliorant ainsi les performances}}
la source
Parfois, même les choses les plus simples peuvent faire la différence. L'un de ces éléments simples qui devraient faire partie de chaque procédure stockée est
SET NOCOUNT ON
. Cette seule ligne de code, placée en haut d'une procédure stockée, désactive les messages que SQL Server renvoie au client après l'exécution de chaque instruction T-SQL. Ceci est effectué pour tousSELECT
,INSERT
,UPDATE
etDELETE
déclarations. La possession de ces informations est pratique lorsque vous exécutez une instruction T-SQL dans une fenêtre de requête, mais lorsque des procédures stockées sont exécutées, il n'est pas nécessaire que ces informations soient transmises au client.En supprimant cette surcharge supplémentaire du réseau, elle peut considérablement améliorer les performances globales de votre base de données et de votre application.
Si vous devez toujours obtenir le nombre de lignes affectées par l'instruction T-SQL en cours d'exécution, vous pouvez toujours utiliser l'
@@ROWCOUNT
option. En émettant uneSET NOCOUNT ON
fonction, cette fonction (@@ROWCOUNT
) fonctionne toujours et peut toujours être utilisée dans vos procédures stockées pour identifier le nombre de lignes affectées par l'instruction.la source