El impacto de una red de comunicaciones obsoleta es cada vez mayor en nuestros SQL Server a medida que otros subsistemas que típicamente producían el fenómeno llamado cuello de botella, el subsistema de disco especialmente, van mejorándose.

También el aumento del volumen de datos o el uso de funcionalidades de replicación/extracción de datos pueden convertir la red en el cuello de botella principal. Esto como veremos parece bastante “incomprensible” en una infraestructura equilibrada, dada la gran evolución que hemos vivido estos últimos años tecnológicamente hablando.

Por ponernos un poco en contexto vamos a comenzar viendo un poco la evolución del ancho de banda  de red a lo largo de los años:

tabla cuello de botella

Esta tabla dista de estar completa pero sí nos da una idea aproximada de más o menos de la “edad” que tienen nuestras infraestructuras de red. Es muy habitual tener controlada la edad de nuestros servidores, saber si ya ha llegado el momento de considerarlos amortizados, etc. pero con la red vemos que hay una tendencia marcada a “estirar” su vida útil mucho más allá. Por ejemplo, el estándar Gigabit Ethernet data de 1995 y aún sigue siendo el predominante en entornos domésticos e incluso en muchos entornos empresariales. El estándar de 10 Gigabit Ethernet, que personalmente pensaba que iba a extenderse mucho más rápido, data del 2001. El disponer de interfaces de 10 Gbit es algo que empieza a encontrarse en muchos servidores, pero desgraciadamente muchas veces la existencia switches, routers y firewalls antiguos acaban haciendo que estas velocidades no sean fácilmente alcanzables.

Por otra parte, vemos que a partir de 2010 se desata una especie de “fiebre” del ancho de banda por el aumento de los entornos cloud y HPC en general. Incluso aparecen otros estándares, como el Omni-Path de Intel, al cual recientemente, dado el desastre que ha supuesto económicamente, ha dejado sin un claro futuro y “abandonado a su suerte”: https://www.hpcwire.com/2019/08/01/report-intel-retreats-on-omni-path/

Aunque Gigabit Ethernet ha ido evolucionando y dispone de velocidades de 25/50 y 100 Gbps Infiniband no se ha quedado atrás con velocidades de hasta 200 Gbps. En la tabla únicamente tenemos datos hasta 2016 por lo que si consideramos los datos más actualizados veremos como tenemos ya estándares Ethernet de 200 Gbps y 400 Gbps disponibles. En esta “carrera” tampoco se ha quedado atrás Infiniband ya que ha presentado estándares de 400 Gbps y 1000 Gbps (1 Tbps).

Desde nuestro punto de vista, Mellanox, la empresa que ha impulsado más Infiniband, es la que actualmente se encuentra mejor posicionada tanto desde el punto de vista de “productos en el mercado” como desde el punto de vista de rendimiento/coste. Es una obviedad que cuando salen nuevos productos que van a un nicho de mercado muy específico tienen un precio prohibitivo. Pero a su vez, presionan a la baja las tecnologías “más obsoletas” cuando realmente tienen aún un gran potencial para muchos escenarios. Por ejemplo, una infraestructura basada en Infiniband de 50 Gbit puede llegar a ser mucho más económica que una de Gigabit Ethernet a 50 Gbit. Un adaptador 50G Ethernet puede costarnos a partir de 500€ mientras que una Infiniband puede costarnos bastante menos y es fácil encontrarlos por la mitad de precio ofreciendo 56Gbps en modo Infiniband y 40 Gbit en modo ethernet.

Para presupuestos aún más ajustados podemos conseguir prácticamente “regaladas” tarjetas que soportan 40Gbps en modo Infiniband y 10 Gb en modo ethernet. En los modelos nuevos vemos que el soporte de este modelo (VPI) es generalizado, e incluso en tarjetas multipuerto antiguas podemos elegir tener un puerto en cada modalidad, por lo que podemos tener con solo una tarjeta acceso a ambos tipos de redes:

conexion cuello de botella

Una vez que tenemos un poco de contexto vamos a comentar algunos de los aspectos donde encontramos más problemas recientemente debido a infraestructuras de red no adecuadas.

Un primer caso típico está relacionado con la realización de backups o la restauración de éstos cuando hablamos de bases de datos de cierto tamaño. No es raro que existan compromisos en los SLAs firmados que, en casos de desastre total y que tengamos que restaurar necesariamente de un full backup, sean imposibles de cumplir por la velocidad alcanzable por la red.

Vamos a realizar unas operaciones de backup utilizando distintas tecnologías, desde 1 Gbit ethernet, lo más básico hoy en día, hasta una tarjeta Infiniband 40/32 Gbits, para ver cuál es el impacto en el proceso.

Para ello vamos a utilizar una base de datos de un tamaño aproximado de 10 GB y posteriormente interpolaremos los resultados que tendríamos con una base de datos de 100GB (x10), 1 TB (x100) y 10 TB (x1000) para que tengamos otros valores de referencia.

Durante la ejecución del backup utilizando 1 Gbps podemos ver cómo se satura fácilmente la red tanto al realizar backups, como al restaurar backups (~85 segundos, ~117 MB/s):

Ethernet cuello de botella

Si subimos a una conexión ethernet de 10Gbps nos encontramos que el rendimiento está por debajo del esperado, ya que nos quedamos en unos 2-3 Gbps aproximadamente (~32 segundos, ~313 MB/s):

Las razones de esto pueden ser variadas, desde configuraciones de las tarjetas, mal procesado de interrupciones, jumbo frames, etc. Si aumentamos el número de ficheros en destino aumentamos el rendimiento, pero nos quedamos en 4 Gbps (~20 s, ~500 MB/s):

send cuello de botella

Ajustando algunos parámetros, como los buffers y el tamaño de transferencia conseguimos arañar algo más, hasta los 4.5 Gbps (~18 segundos, ~555 MB/s)

send cuello de botella 2

A continuación vamos a realizar el cambio de la tarjeta a modo Infiniband, con 40 Gbps de signaling (32 Gbps datarate efectivo ) ante lo que esperaremos una mejora importante:

link speed cuello de botella

Al lanzar de nuevo el backup nos encontramos con que necesitamos lanzar varias veces el backup N veces, para poder calcular una duración media aproximada razonable, dado el pequeño tamaño de la base de datos:

Con estas velocidades de más de 20 Gbps la duración del backup de una base de datos de 10 GB es ínfima, aproximadamente 3.3 segundos lo que nos da una velocidad de aproximadamente 3 GB/s. Quizás podríamos haber llegado a velocidades superiores, pero en este caso ya nos encontramos que es el disco el cuello de botella, y no la red, en este entorno. De hecho, un test a nivel de red (iPerf3) muestra velocidades de hasta 32 Gbps, justo hasta el límite de lo que podemos obtener con esta tarjeta:

Un aspecto que no hemos considerado hasta ahora es el uso de la compresión en los backups por lo que repetiremos los tests con la opción COMPRESSION. Esta es la tabla con todos los resultados y las estimaciones de duración (en segundos) para bases de datos de tamaños de 100 GB, 1 TB y 10 TB:

tabla cuello de botella

Como podemos ver, las diferencias de tiempos son enormes, por lo que debemos tenerlas muy en cuenta a la hora de estimar nuestros SLAs y a la hora de decidir donde debemos invertir en mejorar nuestra infraestructura. Por ejemplo, en el caso de una red de 1 Gbps en el escenario de 10 TB posiblemente no sea aceptable que un backup vaya a necesitar casi 24 horas, un día completo. Esa misma base de datos utilizando la opción más rápida nos llevaría menos de 1 hora, lo cual sí puede ser bastante más aceptable.

El uso de la compresión nos ayudará cuanto mayor sea el cuello de botella causado por la red y tengamos CPU rápida y disponible para comprimir. Si nos fijamos en los datos de la tabla , en el caso de la red más rápida el uso de compresión nos perjudica, ya que no somos capaces de comprimir al ritmo necesario (en este caso la CPU actúa como cuello de botella y no el disco ni la red).

redes cuello de botella

El segundo caso típico, y más preocupante en el día a día, es durante la realización de operaciones de mantenimiento que impliquen el uso de la red. Esto es especialmente evidente cuando tenemos configurado un grupo de disponibilidad con réplicas síncronas, donde toda operación realizada en el primario debe recibir primero la confirmación de escritura en el log del secundario antes de poder dar por completada la operación.

Para analizar esto, vamos a configurar un grupo de disponibilidad con una réplica síncrona y compararemos los tiempos que nos lleva el realizar una operación de mantenimiento como puede ser un rebuild de un índice o una modificación de esquema de una tabla en cada caso. Como baseline tomaremos como referencia el rendimiento “sin grupo de disponibilidad” para cada operación:

use StackOverflow2010
go
-- Baseline 
-- 6901712 KB index
-- 9 seconds 
alter index pk_posts__id on dbo.posts rebuild 
-- 28 seconds
alter table dbo.posts alter column title nvarchar(249)

Una vez obtenidos estos tiempos de referencia, pasaremos a crear un grupo de disponibilidad, en este caso sin apoyo de Windows Clustering ya que no lo necesitamos:

Añadiremos una réplica secundaria en modo síncrono y con failover manual (no relevante en este caso):

hyperv3 cuello de botella

Configuramos el AG con automatic seeding, añadimos la base de datos de prueba y esperamos a que la sincronización finalice:

A continuación, repetiremos la operación de mantenimiento de reconstrucción de índices y de modificación de columna, esta vez ya con el grupo configurado. Comenzaremos por la reconstrucción del índice:

-- AG over 1 Gbps network, synchronous replica
-- 53 seconds
alter index pk_posts__id on dbo.posts rebuild 

Podemos ver como en SQL Server 2017+ el grupo es capaz de exprimir la conexión y llegar a 1 Gbps transmitiendo datos por el log de transacciones:

En cambio, durante la modificación de la columna nos quedamos por debajo, en alrededor de 300 Mbps de media:

-- 31 seconds
alter table dbo.posts alter column title nvarchar(249)

Si realizamos el cambio a la red a 40/32 gbps nos encontramos, desgraciadamente, con un escenario casi simétrico al anterior. En el primer caso de la reconstrucción del índice conseguimos una pequeña mejora, pues el rendimiento es más estable desde un principio, sin oscilaciones, pero la media sigue siendo poco más de 1 Gbps:

-- AG over 32 Gbps network, synchronous replica
-- 48 seconds
alter index pk_posts__id on dbo.posts rebuild 

En el caso de la modificación de columna los tiempos son idénticos con ambas redes:

-- 31 seconds
alter table dbo.posts alter column title nvarchar(249)

Por tanto, contra lo que estamos chocando es contra la problemática inherente de la arquitectura de los grupos de disponibilidad en modo síncrono y que la dejan muy atrás cuando se ralentiza la escritura en el log en modo síncrono. Si cambiamos a modo asíncrono experimentaremos una mejora sustancial en el caso del rebuild y una más marginal en el caso de la modificación de la columna:

-- AG over 32 Gbps network, asynchronous replica
-- 16 seconds
alter index pk_posts__id on dbo.posts rebuild 

-- 28 seconds
alter table dbo.posts alter column title nvarchar(249)

Sin embargo, sigue existiendo cierta ralentización del proceso de rebuild, pues pasamos de 9 segundos a 16 segundos incluso con el AG asíncrono. Probablemente el origen de estos segundos extra son ralentizaciones del log manager que se generen “en cascada” por eventos de llenado del logpool (una zona en memoria de donde leen los AG para evitar el acceso al propio log):

logpool cuello de botella

La anterior imagen se ha obtenido de la sesión de Luke Newport sobre AG: https://www.pass.org/DownloadFile.aspx?File=8565ddb7

Indicar también que en el pasado, durante consultorías de tuning/troubleshooting, hemos experimentado problemas de rendimiento similares o de falta de memoria debido al Log Pool: https://support.microsoft.com/es-es/help/2809338/fix-high-log-write-waits-counter-value-on-a-sql-server-2012-or-sql-ser y https://support.microsoft.com/en-us/help/2769594/sql-server-2012-experiences-out-of-memory-errors

La siguiente tabla muestra los tiempos de cada operación y el impacto que nos genera el grupo de disponibilidad síncrono/asíncrono:

Por tanto, si no utilizamos los grupos de disponibilidad como mecanismo de HA es muy conveniente utilizar el modo asíncrono por defecto. Si lo utilizamos como mecanismo de HA y queremos también utilizar secundarios para lecturas es preferible utilizar una configuración con más nodos, donde el secundario síncrono no esté disponible para lecturas y únicamente tenga que encargarse de mantenerse sincronizado (que tenga un comportamiento pasivo, para entendernos).

Desgraciadamente vemos cómo muy frecuentemente se promueve el uso de los grupos de disponibilidad “de forma indiscriminada”, sin tener en cuenta estos problemas (que también afectan a cargas masivas, procesos pesados de escritura, modificación o borrados, etc.).   Todo ello pese a que existen bastantes referencias en lo que respecta a estas limitaciones:

De todas formas, especialmente en migraciones y entornos standalone/FCI “a modernizar” debemos ser muy cautos y analizar correctamente la carga del servidor para no encontrarnos con “sustos” importantes una vez se realice la migración. También evitaría utilizar versiones anteriores a SQL Server 2016 para AG ya que el rendimiento de la sincronización era considerablemente peor en las versiones SQL Server 2012 y SQL Server 2014.

No debemos olvidarnos tampoco de dimensionar correctamente ya que, por ejemplo, en entornos cloud el ancho de banda suele estar muy condicionado al tamaño y tipo de máquina. Por ejemplo, en Azure podemos tener desde máquinas con anchos de banda muy pobres (como una A1 con 100 Mbps) hasta otras con un enorme ancho de banda (como una HB120Rs con hasta 200 Gbps).

En conclusión, el rendimiento de nuestra red puede tener un impacto significativo en ciertas operaciones como backups remotos. También puede tener un impacto en funcionalidades que hagan un uso intensivo de la red, como los grupos de disponibilidad. Sin embargo, hemos visto como ciertos problemas de rendimiento de los grupos de disponibilidad son propios y derivados de la tecnología utilizada y una mejora en la red no siempre se traduce en una mejora significativa del rendimiento percibido. Es muy importante que nos aseguremos que tenemos un sistema equilibrado, sin demasiados fenómenos de cuello de botella para nuestra carga habitual, así como tener en cuenta que los grupos de disponibilidad pueden tener un impacto muy importante en el rendimiento percibido.

Si te ha gustado nuestro artículo sobre SQL y cuello de botella, desde SolidQ te invitamos a suscribirte a nuestra newsletter para recibir más noticias o tutoriales sobre temas relacionados en nuestro blog.

Rubén Garrigós

Mentor at SolidQ
I am an expert in high-availability enterprise solutions based on SQL Server design, tuning, and troubleshooting. Over the past fifteen years, I have worked with Microsoft data access technologies in leading companies around the world.

Nowadays, I am a Microsoft SQL Server and .NET applications architect with SolidQ. I am certified by Microsoft as a Solution Expert on the Microsoft Data Platform (MSCE: Data Platform) and as a Solution Expert on the Microsoft Private Cloud (MSCE: Private Cloud). As a Microsoft Certified Trainer (MCT), I have taught multiple official Microsoft courses as well as other courses specializing in SQL Server. I have also presented sessions at official events for various Microsoft technologies user groups.
Rubén Garrigós

Latest posts by Rubén Garrigós (see all)