Cuando se diseña una base de datos se siguen algunos reglas aceptadas comúnmente y que cumplen con la teoría formal del diseño de bases de datos. Así entonces nos aseguramos de normalizar nuestra base de datos, de definir las llaves más adecuadas y de alcanzar un diseño que nos permita construir las consultas de la manera más sencilla - la cual casi siempre coincide con la más eficiente -. Sin embargo en la práctica toda esta labor puede venirse al traste cuando nos enfrentamos a volúmenes de tráfico inesperados o con los que nunca nos hemos topado antes.

En esa situación me encontraba con un sitio web, el cual maneja un promedio de 1′000,000 de visitas al mes, es decir alrededor de 33300 visitas al día, lo cual equivale más o menos a 1390 visitas por hora. El problema no lo constituían las 1390 visitas por hora, sino las consultas que se ejecutaban cuando llegaba cada uno de estos visitantes. Cada uno de los clientes realizaba entre 2 y 3 requerimientos a la base de datos, el framework - joomla - por su parte, también requería 1 consulta para el manejo de sesión, es decir que más que a 1390 visitas me estaba enfrentando a (~)5555 consultas por hora, algo que sin duda MySql es capaz de manejar, el problema estaba en el tiempo que las consultas tomaban para su ejecución.

Las tres consultas diferentes a la requerida por joomla estaban tomando alrededor de 1.6 segundos para su ejecución, pero este tiempo crecía de forma exponencial con la llegada de nuevos clientes, el escenario era el siguiente:

Con un sólo cliente una consulta tomaba 1.6 segundos, las 3 consultas seguidas podían tomar alrededor de 5.5 segundos. Con dos clientes era casi imperceptible el aumento en el tiempo requerido, pero la situación cambiaba cuando no eran 2 clientes simultáneos sino 20 o más clientes a la vez.

Cada uno de los clientes lanzaba sus tres consultas en forma casi simultánea. Dado que la primera consulta aún no terminaba cuando se lanzaba la segunda, una nueva conexión con el servidor era creada y lo mismo ocurría con la tercera solicitud y así multiplicado por 20 clientes, gracias a lo cual luego de algunos segundos el servidor tenía cerca de 60 conexiones activas. Adicionalmente dado el aumento en consumo de recursos, el servidor ya no tardaba 5.5 segundos en atender cada cliente, sino que comenzaba a demorarse entre 10 y 15 segundos por consulta.

Cuando la segunda ola de visitantes llegaba al minuto siguiente, este consumo exagerado de recursos comenzaba de nuevo, pero esta vez comenzaba sin la misma cantidad de conexiones disponibles que la primera vez, por lo que al finalizar esta segunda ola el número de conexiones activas era de 80. Luego de tres o cuatro iteraciones más, el número alcanzaba el máximo definido para MySql por defecto (100) y el servidor no podía atender más clientes, con lo que a partir de ese momento y durante los siguientes minutos, cualquier visitante nuevo que llegara a la página se encontraría con un mensaje de “no es posible establecer la conexión con la base de datos”.

La solución por supuesto, no era la de aumentar el número de conexiones disponibles, sino la de reducir al máximo el tiempo requerido por cada consulta, de forma que cada visitante consumiera máximo una conexión para obtener la información requerida, a la vez que liberara rápidamente esta conexión. La forma de lograrlo se encontraba - una vez mas - en los índices. Gracias a la indexación de un campo que se estaba utilizando como criterio, fue posible reducir el tiempo de 1.6 segundos a menos de medio segundo - mucho menos en realidad - y este cambio llevó el número de conexiones abiertas luego del primer minuto de pruebas de 60 a menos de 2 y lo mantuvo en este valor todo el tiempo.

Lección aprendida - de nuevo -: si se tiene una consulta del tipo SELECT campo1, campo2, campo3 FROM tabla1 WHERE criterio1 = “condicion1″ ….. se debe crear un índice sobre criterio1

Referencias adicionales:

  1. http://jamslug.com/wordpress/?p=287
  2. http://jamslug.com/wordpress/?p=285
  3. http://hackmysql.com/case1
  4. http://blog.tuvinh.com/top-20-mysql-best-practices/
Blogged with the Flock Browser
Comparte esto con tus amigos:

2 Respuestas a “La diferencia entre 100 conexiones activas y 2 conexiones activas en MySql”
  1. [...] http://jamslug.com/wordpress/?p=349 AKPC_IDS += “3354,”; [...]

  2. Muy útil, lo tendré muy presente cuando realice múltiples consultas. Quizás el artículo hubiese sido algo más completo si hubieras incluido código de demostración y algún test de prueba.

Deja una Respuesta