Tenemos un servidor MySQL instalado en dos máquinas diferentes, un servidor de prueba y un servidor de producción, ambas ventanas, que es utilizado por una aplicación web.
El problema es que existen enormes diferencias de rendimiento entre las dos máquinas cuando se ejecutan algunas consultas (el servidor de producción es el más lento). La versión de MySQL en ambos servidores es la misma, incluso los archivos de configuración son los mismos (la única diferencia es la ruta de los datos y el hecho de que el servidor de producción no registra nada más que los errores). La diferencia de rendimiento de la que estoy hablando es de 3 o 4 órdenes de magnitud mayor (por ejemplo, una consulta en el servidor de prueba se ejecuta en 0.2 s, mientras que en el servidor de producción se ejecuta en 84 s).
Las consultas ofensivas hacen un uso extensivo de las cláusulas con "WHERE [...] IN [...]", que entiendo que generalmente son muy lentas y deben reemplazarse por JOINs. Sin embargo, la versión de MySQL que estamos usando es 5.6.19, que optimiza esas consultas automáticamente, es por eso que funcionan rápidamente en el servidor de prueba (y están en una parte del programa que no podemos cambiar para que no podamos optimizarlas manualmente de todas formas).
Como dije, la instalación y configuración de MySQL son idénticas, por lo que no tengo ni idea de dónde puede estar el problema. Por un lado, sospecho que debe ser un problema de configuración de algún tipo ya que el programa y la base de datos son iguales, por otro lado, esto no tiene sentido ya que la configuración es idéntica.
Algunos datos en los servidores: Servidor de
prueba:
- Intel Core 2 Quad Q9400 @ 2.66GHz
- 8 GB de RAM
- Windows Server 2008 R2 Standard
Servidor de producción:
- Intel Xeon E5530 @ 2.40GHz
- 5 GB de RAM
- Windows Server 2012 R2 Standard
Editar: Olvidé decir algo importante: se están ejecutando más consultas que usan cláusulas "WHERE ... IN" aparte de las "ofensivas". Se ejecutan rápidamente en ambas máquinas, lo que me sugiere que MySQL las está optimizando correctamente. El hecho de que algunas consultas estén optimizadas cuando otras no lo es es un misterio para mí, SI este es el problema real, lo cual no estoy seguro.
Editar # 2: Aquí está el archivo de configuración para ambos servidores: http://pastebin.ca/2834906
Edición n. ° 3: Aquí está la EXPLICACIÓN de una de las consultas lentas: https://mariadb.org/ea/v36zj La EXPLICACIÓN es exactamente la misma tanto en la prueba como en la producción. La consulta en sí está aquí: http://pastebin.com/VXgBxXmt Se ha formateado con un autoformatter, por lo que quizás no esté muy claro. Como puede ver, es bastante largo y complejo. No se ha generado a mano, son generados automáticamente por el software, que utiliza un dialecto del SQL estándar con algunas funciones.
Además, más información: hemos parcheado temporalmente el problema al reducir los datos en el servidor de producción y eliminar la mayoría de los datos antiguos en la base de datos, que no se utilizarán. Esto no es una solución, por supuesto, ya que también necesitamos los datos antiguos, y será un problema en el futuro. El DB no es tan grande: el DB completo es de 1308 MB, la versión reducida actualmente en producción es de 332 MB.
ACTUALIZACIÓN: ¿RESUELTO?
Creo que he resuelto el problema. Todavía no lo he probado, ya que el servidor de producción se está utilizando, pero el posible problema fue el parámetro "innodb_buffer_pool_size", que se configuró en 182M. En realidad, la línea en el archivo de configuración muestra: innodb_buffer_pool_size = 321, lo cual es un error ya que no tiene el prefijo de la unidad, lo que da un valor no válido (el mínimo es 5242880 según los documentos), y luego lo coloca en el valor anterior . Este valor en el servidor de prueba se estableció en el 321M deseado.
Como dije, no lo he probado por completo. Lo que hice fue reducir el valor de las pruebas y probar la aplicación. Todo va más lento, y la consulta particular que publiqué se ejecuta en 3 minutos.
He puesto a prueba un valor más sensato de 3Gb, que no sé si es una buena idea, así que si alguien tiene algún comentario sobre este valor, lo agradeceré.
Mis conclusiones, el "valor razonable" de 3Gb y la información que utilicé para esto proviene de estas dos publicaciones, particularmente la segunda:
Consulta MySQL, 2 servidores similares, 2 minutos de diferencia en tiempos de ejecución
¿Qué tan grande debe ser mysql innodb_buffer_pool_size?
Publicaré los resultados "reales" cuando actualicemos los valores en el servidor de producción.
Gracias a todos.
RESUELTO
Entonces, finalmente probamos esto en prod, y fue el problema que comenté anteriormente. Puse el valor de innodb_buffer_pool_size en 321M, que es el valor recomendado por el proveedor del SDK que utilizamos, aunque de acuerdo con los enlaces anteriores debería ser de alrededor de 3G para una base de datos de este tamaño y uso.
Sin embargo, todavía tengo dudas: el valor de 321 era un valor no válido (demasiado pequeño), por lo que MySQL tomó otro valor. Mi sospecha es que tomó el número válido anterior, 321M en prueba y 182M en producción, de ahí las diferencias de velocidad. Es solo por curiosidad, pero me gustaría saber si esto es correcto.
Gracias a todos nuevamente por la ayuda.
fuente
Respuestas:
Podría estar volando a ciegas en este caso, pero aquí va ...
En su pregunta y comentarios, declaró lo siguiente:
Debe proporcionar el plan EXPLAIN para una consulta. Como los datos son idénticos, puede que no sea necesario.
Hay un par de cosas que pueden ser diferentes.
Su procesador
Busqué el Intel Core 2 Quad Q9400 @ 2.66GHz (TEST) y el Intel Xeon E5530 @ 2.40GHz (PROD) y encontré una diferencia.
Pensarías que PROD debería ser más rápido.
Su velocidad de bus interno puede ser el cuello de botella. Sospecharía esto porque TEST tiene una velocidad de bus más alta y un multiplicador de bus de 8. ¿Qué es un multiplicador de bus ?
En base a esto, la velocidad del bus interno para AMD (TEST) es al menos 2 veces mayor que Intel (PROD).
ESTADÍSTICAS DE SU ÍNDICE
Como cargó TEST con los mismos datos, una cosa podría haberse pasado por alto. Estoy pensando en las estadísticas del índice. Para TEST, las estadísticas del índice serían bastante nuevas. Para PROD, puede ser obsoleto si las tablas indexadas han experimentado muchos INSERTOS, ACTUALIZACIONES y DELETES.
Ejecutar un SELECT en dos máquinas diferentes con una versión idéntica de mysql, configuraciones idénticas de mysql, conjuntos de datos idénticos e incluso hardware idéntico, podría verse afectado por las estadísticas de índice en la tabla involucrada.
Ejecutaría ANALYZE TABLE en todas las tablas en PROD y TEST y luego intentaría comparar el rendimiento.
fuente