Inspirado por esta pregunta donde hay diferentes puntos de vista en SET NOCOUNT ...
¿Deberíamos usar SET NOCOUNT ON para SQL Server? ¿Si no, porque no?
Que hace Edit 6, el 22 de julio de 2011
Suprime el mensaje "xx filas afectadas" después de cualquier DML. Este es un conjunto de resultados y cuando se envía, el cliente debe procesarlo. Es pequeño, pero medible (ver las respuestas a continuación)
Para los desencadenantes, etc., el cliente recibirá múltiples "filas xx afectadas" y esto causa todo tipo de errores para algunos ORM, MS Access, JPA, etc. (vea las ediciones a continuación)
Antecedentes:
La práctica recomendada general aceptada (pensé hasta esta pregunta) es usarla SET NOCOUNT ON
en disparadores y procedimientos almacenados en SQL Server. Lo usamos en todas partes y un google rápido muestra muchos MVP de SQL Server que también están de acuerdo.
MSDN dice que esto puede romper un .net SQLDataAdapter .
Ahora, esto significa para mí que el SQLDataAdapter se limita a un procesamiento CRUD completamente simple porque espera que el mensaje "n filas afectadas" coincida. Entonces, no puedo usar:
- SI EXISTE para evitar duplicados (mensaje sin filas afectadas) Nota: use con precaución
- DONDE NO EXISTE (menos filas de lo esperado
- Filtre las actualizaciones triviales (por ejemplo, no hay datos que realmente cambien)
- Haga cualquier acceso a la tabla antes (como el registro)
- Ocultar complejidad o desnormalización
- etc.
En la pregunta marc_s (quién sabe sus cosas de SQL) dice que no lo use. Esto difiere de lo que pienso (y también me considero algo competente en SQL).
Es posible que me esté perdiendo algo (siéntase libre de señalar lo obvio), pero ¿qué piensan ustedes por ahí?
Nota: han pasado años desde que vi este error porque no uso SQLDataAdapter hoy en día.
Ediciones después de comentarios y preguntas:
Editar: Más pensamientos ...
Tenemos varios clientes: uno puede usar un C # SQLDataAdaptor, otro puede usar nHibernate de Java. Estos pueden verse afectados de diferentes maneras con SET NOCOUNT ON
.
Si considera los procedimientos almacenados como métodos, entonces es una mala forma (antipatrón) asumir que algunos procesamientos internos funcionan de cierta manera para sus propios fines.
Edición 2: un disparador que rompe la pregunta nHibernate , donde SET NOCOUNT ON
no se puede configurar
(y no, no es un duplicado de esto )
Edición 3: Aún más información, gracias a mi colega MVP
- KB 240882 , problema que causa desconexiones en SQL 2000 y versiones anteriores
- Demostración de aumento de rendimiento
Edición 4: 13 de mayo de 2011
¿Rompe Linq 2 SQL también cuando no se especifica?
Edición 5: 14 jun 2011
Rompe JPA, proceso almacenado con variables de tabla: ¿JPA 2.0 admite variables de tabla de SQL Server?
Edición 6: 15 ago 2011
La cuadrícula de datos "Editar filas" de SSMS requiere SET NOCOUNT ON: Actualizar disparador con GROUP BY
Edición 7: 07 mar 2013
Detalles más detallados de @RemusRusanu:
¿SET NOCOUNT ON realmente hace una gran diferencia de rendimiento?
Respuestas:
Ok, ahora he hecho mi investigación, aquí está el trato:
En el protocolo TDS,
SET NOCOUNT ON
solo guarda 9 bytes por consulta, mientras que el texto "SET NOCOUNT ON" en sí es la friolera de 14 bytes. Solía pensar que123 row(s) affected
se devolvió del servidor en texto plano en un paquete de red separado, pero ese no es el caso. De hecho, es una pequeña estructura llamadaDONE_IN_PROC
incrustada en la respuesta. No es un paquete de red separado, por lo que no se desperdician viajes de ida y vuelta.Creo que puede mantener el comportamiento de conteo predeterminado casi siempre sin preocuparse por el rendimiento. Sin embargo, hay algunos casos en los que calcular el número de filas de antemano afectaría el rendimiento, como un cursor de solo avance. En ese caso, NOCOUNT podría ser una necesidad. Aparte de eso, no hay absolutamente ninguna necesidad de seguir el lema "usar NOCOUNT siempre que sea posible".
Aquí hay un análisis muy detallado sobre la insignificancia de la
SET NOCOUNT
configuración: http://daleburnett.com/2014/01/everything-ever-wanted-know-set-nocount/fuente
DONINPROC
ElDONE
mensaje (RPC) o (BATCH) se transmite con elrowcount
conjunto a las filas afectadas, mientras que eldone_count
indicador estrue
, independientemente de siNO_COUNT
es asíON
. Depende de la implementación de la biblioteca del cliente en los casos en que la consulta contiene sentencias SELECT o llamadas RPC que sí seleccionan, puede requerir deshabilitar el conteo ... CUANDO está deshabilitado, las filas todavía se cuentan para la instrucción select, pero el indicadorDONE_COUNT
está configurado enfalse
. Siempre lea lo que su cliente lib sugiere, ya que interpretará el flujo de token (mensaje) en lugar de ustedMe llevó mucho tiempo encontrar cifras reales de referencia en torno a NOCOUNT, así que pensé en compartir un resumen rápido.
fuente
SET NOCOUNT OFF;
y es por eso que piensan que no están obteniendo bytes adicionales en respuesta. El punto de referencia exacto sería utilizarloSET NOCOUNT ON
en elSET NOCOUNT OFF
procedimiento almacenado a la izquierda y a la derecha. De esta manera, obtendrá el paquete TDS conDONEINPROC (SET NOCOUNT ...)
diez de nuevoDONEINPROC (INSERT statement)
, y luegoRETURNVALUE(@@ROWCOUNT)
,RETURNSTATUS 0
para sp y finalmenteDONPROC
. ¡El error está ahí porque el segundo sp no tiene SET NOCOUNT OFF en el cuerpo!Cuando SET NOCOUNT está activado, el recuento (que indica el número de filas afectadas por una instrucción Transact-SQL) no se devuelve. Cuando SET NOCOUNT está desactivado, se devuelve el recuento. Se usa con cualquier instrucción SELECT, INSERT, UPDATE, DELETE.
La configuración de SET NOCOUNT se establece en tiempo de ejecución o ejecución y no en tiempo de análisis.
SET NOCOUNT ON mejora el rendimiento del procedimiento almacenado (SP).
Sintaxis: SET NOCOUNT {ON | APAGADO }
Ejemplo de SET NOCOUNT ON:
Ejemplo de SET NOCOUNT OFF:
fuente
Supongo que hasta cierto punto es un problema de DBA vs. desarrollador.
Como desarrollador en su mayoría, diría que no lo use a menos que sea absolutamente necesario, porque usarlo puede romper su código ADO.NET (según lo documentado por Microsoft).
Y supongo que como DBA, estarías más del otro lado: úsalo siempre que sea posible a menos que realmente debas evitar su uso.
Además, si sus desarrolladores alguna vez usan los "Registros afectados" que devuelve la
ExecuteNonQuery
llamada al método de ADO.NET , están en problemas si todos los usan,SET NOCOUNT ON
ya que en este caso, ExecuteNonQuery siempre devolverá 0.También vea la publicación del blog de Peter Bromberg y revise su posición.
Entonces, todo se reduce a quién puede establecer los estándares :-)
Bagazo
fuente
Si está diciendo que también podría tener diferentes clientes, hay problemas con ADO clásico si SET NOCOUNT no está activado.
Uno que experimento regularmente: si un procedimiento almacenado ejecuta una serie de declaraciones (y, por lo tanto, se devuelven varios mensajes de "xxx filas afectadas"), ADO parece no manejar esto y arroja el error "No se puede cambiar la propiedad ActiveConnection de un objeto Recordset que tiene un objeto Command como fuente ".
Por lo tanto, generalmente recomiendo activarlo a menos que haya una muy buena razón para no hacerlo. Es posible que haya encontrado la muy buena razón por la que necesito ir y leer más.
fuente
A riesgo de hacer las cosas más complicadas, animo una regla ligeramente diferente a todas las que veo arriba:
NOCOUNT ON
en la parte superior de un proceso, antes de realizar cualquier trabajo en el proceso, pero también siempre deSET NOCOUNT OFF
nuevo, antes de devolver cualquier conjunto de registros del proceso almacenado.Entonces, "generalmente no cuente, excepto cuando en realidad está devolviendo un conjunto de resultados". No sé de qué manera esto puede romper cualquier código de cliente, significa que el código de cliente nunca necesita saber nada sobre los procesos internos, y no es particularmente oneroso.
fuente
Con respecto a los desencadenantes que rompen NHibernate, tuve esa experiencia de primera mano. Básicamente, cuando NH hace una ACTUALIZACIÓN, espera cierto número de filas afectadas. Al agregar SET NOCOUNT ON a los disparadores, obtiene el número de filas de nuevo a lo que NH esperaba, solucionando así el problema. Así que sí, definitivamente recomendaría desactivarlo para los desencadenantes si usa NH.
En cuanto al uso en SP, es una cuestión de preferencia personal. Siempre había desactivado el recuento de filas, pero, de nuevo, no hay argumentos realmente fuertes de ninguna manera.
En una nota diferente, realmente debería considerar alejarse de la arquitectura basada en SP, entonces ni siquiera tendrá esta pregunta.
fuente
Quería verificar que 'SET NOCOUNT ON' no guarda un paquete de red ni un viaje de ida y vuelta
Utilicé un SQLServer 2017 de prueba en otro host (utilicé una 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
Luego rastreé los paquetes en el puerto 1433 con la herramienta 'Wireshark': botón 'capturar filtro' -> 'puerto 1433'exec procNoCount
Este es el paquete de respuesta:
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
Este es el paquete de respuesta:
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
En la línea 40 puedo ver '07', que es el número de 'filas afectadas'. Se incluye en el paquete de respuesta. Sin paquete extra.
Sin embargo, tiene 13 bytes adicionales que podrían guardarse, pero probablemente no valen más que reducir los nombres de columna (por ejemplo, 'ManagingDepartment' a 'MD')
Así que no veo ninguna razón para usarlo para el rendimiento
PERO, como otros mencionaron, puede romper ADO.NET y también me topé con un problema usando python: MSSQL2008 - Pyodbc - El SQL anterior no era una consulta
Entonces, probablemente sea un buen hábito ...
fuente
Esta línea de código se usa en SQL para no devolver las filas de números afectadas en la ejecución de la consulta. Si no requerimos el número de filas afectadas, podemos usar esto ya que esto ayudaría a ahorrar el uso de memoria y aumentaría la velocidad de ejecución de la consulta.
fuente
ESTABLECER CUENTA El código anterior detendrá el mensaje generado por el motor del servidor sql en la ventana de resultados frontal después de la ejecución del comando DML / DDL.
¿Por qué lo hacemos? Como el motor del servidor SQL toma algunos recursos para obtener el estado y generar el mensaje, se considera una sobrecarga en el motor del servidor SQL. Por lo tanto, configuramos el mensaje de no cuenta.
fuente
Un lugar que
SET NOCOUNT ON
realmente puede ayudar es donde está haciendo consultas en un bucle o un cursor. Esto puede sumar mucho tráfico de red.Al activar las estadísticas del cliente en SSMS, se ejecuta
EXEC NoCountOn
yEXEC NoCountOff
muestra que hubo un tráfico adicional de 390 KB en el NoCountOff:Probablemente no sea ideal para hacer consultas en un bucle o cursor, pero tampoco vivimos en el mundo ideal :)
fuente
Sé que es una pregunta bastante antigua. Pero solo para actualizar.
La mejor manera de usar "SET NOCOUNT ON" es ponerlo como una primera declaración en su SP y volverlo a APAGAR justo antes de la última declaración SELECT.
fuente
No sé cómo probar SET NOCOUNT ON entre el cliente y SQL, así que probé un comportamiento similar para otro comando SET "SET TRANSACTION ISVELATION LEVEL LEAD UNCIMMITTED"
Envié un comando desde mi conexión cambiando el comportamiento predeterminado de SQL (READ COMMITTED), y se cambió para los siguientes comandos. Cuando cambié el nivel de AISLAMIENTO dentro de un procedimiento almacenado, no cambió el comportamiento de conexión para el siguiente comando.
Conclusión actual
Creo que esto es relevante para otros comandos SET como "SET NOCOUNT ON"
fuente
NOCOUNT
if (establecer sin recuento == off)
{entonces mantendrá datos de cuántos registros afectados, así que reduzca el rendimiento} más {no rastreará el registro de cambios, por lo tanto, mejorará el rendimiento}}
fuente
A veces, incluso las cosas más simples pueden marcar la diferencia. Uno de estos elementos simples que deberían formar parte de cada procedimiento almacenado es
SET NOCOUNT ON
. Esta línea de código, colocada en la parte superior de un procedimiento almacenado, apaga los mensajes que SQL Server envía al cliente después de que se ejecuta cada instrucción T-SQL. Esto se realiza para todasSELECT
,INSERT
,UPDATE
, yDELETE
declaraciones. Tener esta información es útil cuando ejecuta una instrucción T-SQL en una ventana de consulta, pero cuando se ejecutan los procedimientos almacenados, no es necesario que esta información se devuelva al cliente.Al eliminar esta sobrecarga adicional de la red, puede mejorar en gran medida el rendimiento general de su base de datos y aplicación.
Si aún necesita obtener el número de filas afectadas por la instrucción T-SQL que se está ejecutando, aún puede usar la
@@ROWCOUNT
opción. Al emitir unaSET NOCOUNT ON
función this (@@ROWCOUNT
) todavía funciona y aún se puede usar en sus procedimientos almacenados para identificar cuántas filas se vieron afectadas por la instrucción.fuente