Mi empresa utiliza una aplicación que tiene problemas de rendimiento bastante importantes. Hay una serie de problemas con la base de datos en sí, en los que estoy trabajando, pero muchos de los problemas están relacionados únicamente con la aplicación.
En mi investigación descubrí que hay millones de consultas que llegan a la base de datos de SQL Server que consultan tablas vacías. Tenemos alrededor de 300 tablas vacías y algunas de esas tablas se consultan hasta 100-200 veces por minuto. Las tablas no tienen nada que ver con nuestra área de negocios y son esencialmente partes de la aplicación original que el proveedor no eliminó cuando mi empresa las contrató para producir una solución de software para nosotros.
Además del hecho de que sospechamos que nuestro registro de errores de la aplicación se está inundando con errores relacionados con este problema, el proveedor nos asegura que no hay un impacto en el rendimiento o la estabilidad ni de la aplicación ni del servidor de la base de datos. El registro de errores se inunda en la medida en que no podemos ver más de 2 minutos de errores para hacer diagnósticos.
El costo real de estas consultas obviamente será bajo en términos de ciclos de CPU, etc. ¿Pero alguien puede sugerir cuál sería el efecto en SQL Server y la aplicación? Sospecharía que la mecánica real de enviar una solicitud, confirmarla, procesarla, devolverla y acusar recibo de la solicitud tendría un impacto en el rendimiento.
Utilizamos SQL Server 2008 R2, Oracle Weblogic 11g para la aplicación.
@ Frisbee: Para resumir, creé una tabla que contiene el texto de consulta que golpeó las tablas vacías en la base de datos de la aplicación, luego pregunté por todos los nombres de tablas que sé que están vacíos y obtuve una lista muy larga. El mayor éxito fue de 2.7 millones de ejecuciones durante 30 días de tiempo de actividad, teniendo en cuenta que la aplicación generalmente se usa de 8 am a 6 pm, por lo que esos números están más concentrados en las horas de funcionamiento. Múltiples tablas, múltiples consultas, probablemente algunas relacionadas a través de combinaciones, otras no. El primer éxito (2.7 millones en ese momento) fue una simple selección de una sola tabla vacía con una cláusula where, sin uniones. Esperaría que las consultas más grandes con uniones a las tablas vacías pudieran incluir actualizaciones a las tablas vinculadas, pero lo comprobaré y actualizaré esta pregunta lo antes posible.
Actualización: Hay 1000 consultas con un recuento de ejecución de entre 1043 y 4622614 (más de 2.5 meses). Tendré que cavar más para saber cuándo se origina el plan en caché. Esto es solo para darle una idea del alcance de las consultas. La mayoría son razonablemente complejos con más de 20 uniones.
@ srutzky- sí, creo que hay una columna de fecha relacionada con el momento en que se compiló el plan, por lo que sería interesante, así que lo comprobaré. Me pregunto si los límites de subprocesos serían un factor en absoluto cuando el SQL Server se encuentra en un clúster de VMware. Pronto será un Dell PE 730xD dedicado, afortunadamente.
@Frisbee - Perdón por la respuesta tardía. Como sugirió, ejecuté un select * de la tabla vacía 10,000 veces en 24 subprocesos usando SQLQueryStress (en realidad 240,000 iteraciones) y alcancé 10,000 Solicitudes de lote / seg inmediatamente. Luego reduje a 1000 veces más de 24 hilos y llegué a menos de 4.000 solicitudes de lote / segundo. También probé 10,000 iteraciones en solo 12 subprocesos (por lo tanto, 120000 iteraciones totales) y esto produjo un sostenido 6,505 lotes / seg. El efecto en la CPU fue realmente notable, alrededor del 5-10% del uso total de la CPU durante cada ejecución de prueba. Las esperas de la red fueron insignificantes (como 3 ms con el cliente en mi estación de trabajo), pero el impacto de la CPU fue seguro, lo que es bastante concluyente en lo que a mí respecta. Parece reducirse al uso de la CPU y un poco de archivo de base de datos innecesario IO. El total de ejecuciones / segundo funciona en poco menos de 3000, que es más que en producción, sin embargo, estoy probando solo una de las docenas de consultas como esta. El efecto neto de cientos de consultas que llegan a tablas vacías a una velocidad de entre 300 y 4000 veces por minuto, por lo tanto, no sería insignificante cuando se trata del tiempo de CPU. Todas las pruebas realizadas contra un PE 730xD inactivo con doble matriz flash y 256 GB de RAM, 12 núcleos modernos.
@ srutzky- buen pensamiento. SQLQueryStress parece utilizar la agrupación de conexiones de forma predeterminada, pero de todos modos eché un vistazo y descubrí que sí, la casilla para la agrupación de conexiones está marcada. Actualización a seguir
@ srutzky: la agrupación de conexiones aparentemente no está habilitada en la aplicación, o si lo está, no está funcionando. Hice un seguimiento del generador de perfiles y descubrí que las conexiones tienen EventSubClass "1 - No agrupado" para los eventos de inicio de sesión de auditoría.
RE: Agrupación de conexiones: verificó los weblogics y encontró la agrupación de conexiones habilitada. Corrió más rastros en vivo y encontró signos de agrupación que no ocurren correctamente / en absoluto:
Y así es como se ve cuando ejecuto una sola consulta sin combinaciones en una tabla poblada; las excepciones dicen "Se produjo un error relacionado con la red o específico de la instancia al establecer una conexión con SQL Server. No se encontró el servidor o no fue accesible. Verifique que el nombre de la instancia sea correcto y que SQL Server esté configurado para permitir conexiones remotas. (proveedor: proveedor de canalizaciones con nombre, error: 40 - No se pudo abrir una conexión a SQL Server) "Tenga en cuenta el contador de solicitudes por lotes. Hacer ping al servidor durante el tiempo en que se generan las excepciones da como resultado una respuesta de ping exitosa.
Actualización: dos ejecuciones de prueba consecutivas, la misma carga de trabajo (seleccione * fromEmptyTable), agrupación habilitada / no habilitada. Un poco más de uso de CPU y muchas fallas y nunca supera las 500 solicitudes por lote / seg. Las pruebas muestran 10,000 lotes / segundo y no hay fallas con la agrupación activada, y alrededor de 400 lotes / segundo y luego muchas fallas debido a la desactivación de la agrupación. Me pregunto si estas fallas están relacionadas con la falta de disponibilidad de conexión.
@ srutzky- Seleccione Count (*) de sys.dm_exec_connections;
Agrupación habilitada: 37 consistentemente, incluso después de que se detiene la prueba de carga
Agrupación deshabilitada: 11-37 dependiendo de si se
producen o no excepciones en SQLQueryStress, es decir: cuando esos canales aparecen en el
gráfico Batches / sec, las excepciones ocurren en SQLQueryStress, y el
número de conexiones cae a 11, luego vuelve gradualmente a 37 cuando los lotes comienzan a alcanzar su punto máximo y no se producen las excepciones. Muy, muy interesante
Las conexiones máximas en ambas instancias de prueba / en vivo se establecen en el valor predeterminado de 0.
He verificado los registros de la aplicación y no puedo encontrar problemas de conectividad, sin embargo, solo hay un par de minutos de registro disponibles debido a la gran cantidad y el tamaño de los errores, es decir: muchos errores de seguimiento de la pila. Un colega en soporte de aplicaciones informa que se produce un número considerable de errores HTTP relacionados con la conectividad. Parecería basado en esto, que por alguna razón la aplicación no está agrupando conexiones correctamente y como resultado, el servidor se está quedando sin conexiones repetidamente. Buscaré más en los registros de aplicaciones. Me pregunto ¿hay alguna manera de demostrar que esto está sucediendo en la producción desde el lado del servidor SQL?
@ srutzky- Gracias. Revisaré la configuración de weblogic mañana y la actualizaré. Sin embargo, estaba pensando en las meras 37 conexiones: si SQLQueryStress está haciendo 12 subprocesos a 10,000 iteraciones = 120,000 declaraciones de selección no agrupadas, ¿no debería eso significar que cada selección crea una conexión distinta a la instancia de SQL?
@ srutzky: los Weblogics están configurados para agrupar conexiones, por lo que debería funcionar bien. La agrupación de conexiones se configura de esta manera, en cada uno de los 4 weblogics de carga equilibrada:
- Capacidad inicial: 10
- Capacidad Máxima: 50
- Capacidad mínima: 5
Cuando aumento el número de subprocesos que ejecutan la selección de la consulta de tabla vacía, el número de conexiones alcanza un pico de alrededor de 47. Con la agrupación de conexiones deshabilitada, veo consistentemente un menor número de solicitudes de lote / segundo (de 10,000 a aproximadamente 400). Lo que sucederá cada vez es que las 'excepciones' en SQLQueryStress ocurren poco después de que los lotes / seg entren en un canal. Está relacionado con la conectividad, pero no puedo entender exactamente por qué sucede esto. Cuando no se están ejecutando pruebas, # connections baja a aproximadamente 12.
Con la agrupación de conexiones deshabilitada, tengo problemas para entender por qué ocurren las excepciones, pero ¿tal vez es una pregunta / pregunta de stackExchange completamente diferente para Adam Machanic?
@srutzky Me pregunto, entonces, ¿por qué ocurren las excepciones sin la agrupación habilitada, a pesar de que SQL Server no se está quedando sin conexiones?
SELECT COUNT(*) FROM sys.dm_exec_connections;
para ver si el valor es muy diferente entre tener la agrupación habilitada o no. Basado en esos errores, creo que habría muchas más conexiones cuando la agrupación esté deshabilitada.
Pooling=false
o Max Pool Size
?