Cuando realizamos nuestros proyectos de tuning de bases de datos habitualmente nos concentramos en el servidor SQL Server principalmente y en optimizar su modelo relacional, el indexado, consultas ineficientes, etc. Debido a las características de algunas arquitecturas cliente-servidor puras nos encontramos con que ésta optimización por sí sola no consigue mejorar el rendimiento de forma significativa. El motivo principal suele ser que aunque nuestro servidor SQL Server esté en plena forma y resuelva las consultas y ejecute procedimientos almacenados a una velocidad endiablada la red y el exceso de round-trips al servidor echan por tierra el rendimiento general.

Cuando nos encontramos optimizando el servidor, un síntoma que algo ocurre en la red es cuando las esperas de tipo NETWORKIO son muy elevadas respecto al global de esperas del servidor. Los motivos de esto son variados:

  • Las consultas devuelven una gran cantidad de datos. Este es el escenario típico cuando, por ejemplo, se realiza paginado poco eficiente en cliente. Si lanzamos una consulta que nos devuelva un millón de clientes para luego en la aplicación mostrarlos de 100 en 100 estamos generando una gran cantidad de tráfico innecesario. Tenemos que pensar que este comportamiento multiplicado por cada uno de nuestros clientes conectados puede tirar por tierra el rendimiento global por saturación en la red. El paginado en cliente o el uso de estrategias de caché puedes ayudar en gran medida a aliviar este problema.
  • La conexión de red tiene una latencia muy alta. Típicamente las aplicaciones cliente lanzan numerosos batches para obtener la información para «pintar» una pantalla de la aplicación. El modelo de programación multithread no está, desgraciadamente, muy extendido con lo que finalmente nos encontramos con un conjunto de batches que deben ser lanzados contra la base de datos de forma secuencial. Las bases de datos están optimizadas para trabajar con múltiples peticiones de forma simultánea de forma que con casi total probabilidad el lanzar dichos batches en paralelo reduciría mucho el tiempo global de respuesta. Esta situación se vuelve especialmente crítica en redes WAN lentas donde esta latencia pasa de los pocos milisegundos que tenemos en una LAN típica a cientos de milisegundos. Para escenarios de este tipo es habitual recurrir a replicación para mantener una copia de los datos en local o bien en un servidor local. De esta forma únicamente el tráfico de la replicación será el que deberá pasar por la red dejando de representar un cuello de botella para la aplicación local.
  • Operaciones masivas por red. En ocasiones procesos de backup, de importación masiva de datos o similares se lanzan durante periodos de actividad de la base de datos. Al ser la red un recurso crítico para el tiempo de respuesta, cuando alguna de estas actividades se está realizando la lentitud afectará a todo el sistema aunque no tengamos problemas de IO en disco. No olvidemos que la red es un recurso IO tan importante como el disco en sistemas de alto rendimiento. Para solucionar este problema podemos incrementar el ancho de banda de la red, por ejemplo haciendo teaming de un interfaz gigabit para obtener 2 gigabits o incluso migrando a los nuevos interfaces Ethernet de 10 gigabits para reducir tanto la latencia como el ancho de banda disponible. Otra alternativa es añadir QoS (Quality of Service) sobre la pila TCP/IP (bien a nivel software o bien a nivel hardware) de forma que prioricemos el acceso de nuestros clientes sobre el acceso de los servidores de copia, carga masiva, etc.

Para ayudarnos en estas labores de optimización de red contaremos con varios aliados. El primero es nuestro querido Performance Monitor que nos permitirá obtener estadísticas sobre los adaptadores de red con lo cual detectaremos si tenemos congestión en su uso. También la cantidad de batches por segundo que se procesan en el servidor puede ser un indicador de problemas de red cuando el ratio entre usuarios y éste sea muy elevado. Dicho en otras palabras, normalmente si un cliente realiza 50 batches por segundo o más podemos empezar a pensar que debemos analizar con Profiler y una traza adecuada que está haciendo y ver de qué forma podemos reducir esa presión sobre el servidor modificando ese comportamiento.

En otras situaciones las estadísticas de cliente con management studio son de tremenda utilidad. Para activar esta funcionalidad deberemos activar la opción «Include Client Statistics»

 

Éstas estadísticas nos proporcionan información sobre el número de paquetes TDS enviados/recibidos (TDS es el protocolo interno que utiliza SQL Server), número de filas devueltas, número de roundtrips al servidor, bytes enviados y recibidos, etc. Además esta información nos la mostrará de forma que podemos comparar varias ejecuciones y determinar así el impacto de distintas alternativas para un mismo proceso.

Vamos a ver como con esta ayuda podemos aportar datos para recomendar el uso de único batch para un proceso o sin embargo no es rentable la modificación.

En este ejemplo vamos a lanzar en primera instancia el siguiente conjunto de batches:

select top 10 * from adventureworks.person.contact order by middlename

go 10 — Lanzamos 10 veces esta consulta como un batch

select top 10 * from adventureworks.person.address order by city desc

go 10 — Lanzamos 10 veces esta consulta como un batch

select top 10 * from adventureworks.person.contact order by phone desc

go 10 — Lanzamos 10 veces esta consulta como un batch

 

A continuación lanzaremos estas mismas consultas pero todas en un único batch que contendrá las 30 consultas que tenemos en total. Los resultados los podemos ver como Trial 1 y Trial 2 respectivamente:

Como podemos ver, la ejecución de múltiples batches genera un tiempo total de ejecución mayor (300% mayor) y un aumento en un 600% en las esperas de la respuesta del servidor. Estas diferencias que son muy abultadas se encuentran al procesar estas consultas contra mi servidor SQL Server en mi máquina. Con un servidor remoto las diferencias serían mucho más abultadas (si, más aún J). Si nos fijamos en el número de roundtrips al servidor vemos que la alternativa con un único batch requiere únicamente de una ida y venida del servidor mientras que la anterior requiere de 30 (una por batch). Si tuviéramos una latencia de 100 milisegundos ( y ejecutamos los batches de forma secuencial como suele ser habitual) estos roundtrips añadirían ya 3 segundos adicionales a la ejecución del proceso. Por otra parte es también típico que las aplicaciones cliente servidor remotas utilicen líneas ADSL asimétricas con lo cual el ancho de banda de subida esté más limitado. El número de bytes enviados se reduce en un 20% al utilizar un único batch respecto al uso de múltiples batches.

En conclusión diremos que las estadísticas de cliente nos permiten aportar datos y probar la eficiencia de diferentes alternativas en lo que al uso o abuso de la red se refiere J

Happy tuning!

 

 

 

Rubén Garrigós