sql >> Base de Datos >  >> RDS >> Database

Sorpresas y suposiciones de rendimiento:SET NOCOUNT ON

Si alguna vez usó Management Studio, este mensaje de salida probablemente le resultará familiar:

(1 fila(s) afectada(s))

Esto proviene de DONE_IN_PROC de SQL Server mensaje, que se envía al completar con éxito cualquier declaración SQL que haya devuelto un resultado (incluida la recuperación de un plan de ejecución, por lo que ve dos de estos mensajes cuando en realidad solo ha ejecutado una única consulta).

Puede suprimir estos mensajes con el siguiente comando:

SET NOCOUNT ON;

¿Por qué harías eso? Porque estos mensajes son habladores ya menudo inútil . En mis presentaciones sobre malos hábitos y mejores prácticas, a menudo hablo de agregar SET NOCOUNT ON; a todos los procedimientos almacenados y activarlo en el código de la aplicación que envía consultas ad hoc. (Sin embargo, durante la depuración, es posible que desee una marca para volver a activar los mensajes, ya que la salida puede ser útil en esos casos).

Siempre agregué el descargo de responsabilidad de que el consejo de activar esta opción en todas partes no es universal; depende. Los conjuntos de registros ADO de la vieja escuela en realidad los interpretaron como conjuntos de resultados, por lo que agregarlos a las consultas después del hecho podría romper las aplicaciones que ya las están omitiendo manualmente. Y algunos ORM (tos, NHibernate, tos ) en realidad analizan los resultados para determinar el éxito de los comandos DML (¡uf!). Pruebe sus cambios.

Sé que en un momento me probé a mí mismo que estos mensajes parlanchines podrían afectar el rendimiento, especialmente en una red lenta. Pero ha pasado mucho tiempo y la semana pasada Erin Stellato me preguntó si alguna vez lo había documentado formalmente. No lo he hecho, así que aquí va. Tomaremos un ciclo muy simple, donde actualizaremos una variable de tabla un millón de veces:

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();

Un par de cosas que podrías notar:

  • El panel de mensajes está inundado con instancias de (1 row(s) affected) mensaje:

  • El SELECT SYSDATETIME(); no se presenta en el panel de resultados hasta que se haya completado todo el lote. Esto se debe a las inundaciones.
  • Este lote tardó unos 21 segundos en ejecutarse.

Ahora, repitamos esto sin el DONE_IN_PROC mensajes, cambiando SET NOCOUNT OFF; para SET NOCOUNT ON; y ejecutarlo de nuevo.

Si bien el panel de mensajes ya no estaba inundado con las filas de mensajes afectados, el lote todavía tardó ~21 segundos en ejecutarse.

Entonces pensé, espera un segundo, sé lo que está pasando. Estoy en una máquina local, sin red involucrada, usando memoria compartida, solo tengo SSD y montones y montones de RAM...

Así que repetí las pruebas usando mi copia local de SSMS contra una base de datos Azure SQL remota:una versión estándar, S0, V12. Esta vez, las consultas tardaron mucho más, incluso después de reducir las iteraciones de 1 000 000 a 100 000. Pero, de nuevo, no hubo una diferencia tangible en el rendimiento si DONE_IN_PROC los mensajes se enviaban o no. Ambos lotes tardaron unos 104 segundos y esto se repitió en muchas iteraciones.

Conclusión

Durante años, había estado operando bajo la impresión de que SET NOCOUNT ON; era una parte fundamental de cualquier estrategia de rendimiento. Esto se basó en observaciones que hice en, posiblemente, una era diferente, y que es menos probable que se manifieste hoy.

Dicho esto, continuaré usando SET NOCOUNT ON , incluso si en el hardware actual no hay una diferencia notable en el rendimiento. Todavía me siento muy convencido de minimizar el tráfico de red cuando sea posible. Debería considerar implementar una prueba en la que tenga un ancho de banda mucho más restringido (¿quizás alguien tenga un CD de AOL que me pueda prestar?), o tener una máquina en la que la cantidad de memoria sea inferior a los límites del búfer de salida de Management Studio, para no es un impacto potencial en los peores escenarios. Mientras tanto, si bien es posible que no cambie el rendimiento percibido de su aplicación, aún puede ayudar a su billetera a activar siempre esta opción de configuración, especialmente en situaciones como Azure, donde se le puede cobrar por el tráfico de salida.