High Performance MySQL [Cap. 3: Perfilado del rendimiento del servidor]

High Performance MySQL

Lo esencial
  • Optimizar significa reducir el tiempo de respuesta, y no puedes reducir lo que no has medido.
  • Un perfil descompone el tiempo en tareas, agrupa las similares y las ordena. Arregla primero la línea de arriba.
  • Pondera por frecuencia: una mejora de 2× en una consulta que es el 5% de la carga es mejor que nada; una mejora del 20% en una que es el 60% la supera.
  • Demuestra un diagnóstico antes de actuar sobre él. La explicación conocida a menudo es la equivocada.

Las tres preguntas

Casi cualquier queja de rendimiento se reduce a una de tres preguntas: ¿el servidor hace su trabajo de forma eficiente?, ¿por qué esta consulta concreta es lenta? y ¿qué causa ese bloqueo ocasional que nadie consigue reproducir? El profiling es la manera de responderlas con evidencia en lugar de intuición.

El libro define el rendimiento como tiempo de respuesta, así que el objetivo del profiling es explicar a dónde va ese tiempo. A veces la respuesta es trabajo que puedes eliminar: un índice que falta, una ordenación innecesaria. Otras veces es que cada paso es necesario, y eso es igual de valioso, porque evita que sigas puliendo una consulta que ya es todo lo rápida que puede ser.

Qué aspecto tiene un perfil

Medir una tarea de principio a fin te da un solo número. Un perfil la divide en tareas hijas, fusiona las repetidas y las ordena por su parte del tiempo total. El resultado se lee como una factura ordenada:

COLUMNASIGNIFICADO
PosiciónLugar según su parte del tiempo de respuesta total.
Tiempo totalSumado sobre todas las apariciones de la tarea.
PorcentajePorcentaje de todo el tiempo medido.
LlamadasCuántas veces se ejecutó la tarea.
Tiempo por llamadaEl total dividido entre las llamadas: separa lo "lento" de lo "frecuente".

Hay dos variantes. El perfilado del tiempo de ejecución muestra a dónde va el trabajo de CPU y sirve para consultas limitadas por cómputo. El análisis de esperas muestra el tiempo pasado bloqueado en E/S o en bloqueos, que es donde vive la mayoría de las consultas lentas en una base de datos.

Empieza por la aplicación

Antes de perfilar MySQL, perfila el código que lo llama. Un sistema de monitorización del rendimiento de la aplicación (APM) que mide cada petición y la divide en spans (llamadas a la base de datos, APIs externas, renderizado) te dice si la base de datos es siquiera el problema, y qué consultas importan más a los usuarios. El trabajo en la base de datos sin impacto visible para el usuario normalmente puede esperar.

Perfilar la carga del servidor

Cuando todavía no sabes qué consultas hacen daño, míralas todas. El slow query log registra las consultas que superan long_query_time; poner ese umbral en 0 lo captura todo. Registrar cuesta algo de E/S y de disco, así que rota los archivos y no dejes el registro completo activado a ciegas. Herramientas como pt-query-digest normalizan luego las consultas en huellas (fingerprints) y las ordenan por tiempo total.

En MySQL 8, el Performance Schema ofrece la misma información sin archivos de log: events_statements_summary_by_digest ya agrega las sentencias por huella, con recuentos, latencia y filas examinadas por digest.

Perfilar una sola consulta

Cuando ya tienes un sospechoso, descomponlo. El libro usa SHOW PROFILE, que lista las etapas por las que pasó una consulta (abrir tablas, enviar datos, crear una tabla temporal, ordenar) con su duración. Está obsoleto en MySQL 8; las tablas de etapas del Performance Schema (events_stages_history_long) contienen los mismos datos y se pueden agrupar con SQL normal:

SELECT event_name, COUNT(*) AS calls, SUM(timer_wait) / 1e9 AS total_ms
FROM performance_schema.events_stages_history_long
WHERE nesting_event_id = <statement event id>
GROUP BY event_name
ORDER BY total_ms DESC;

Agrupar importa: una etapa que aparece cinco veces en la salida en bruto es una sola línea en el perfil. Una consulta que pasa la mitad de su tiempo copiando a una tabla temporal te dice exactamente dónde mirar; una ordenación que ocupa el 5% te dice que no pierdas el tiempo con ella.

Los contadores de estado complementan la medición por etapas. Comparar SHOW SESSION STATUS antes y después de una consulta muestra cuántas filas leyó por cada vía de acceso (Handler_read_*), si creó tablas temporales en disco y si ordenó.

Problemas intermitentes

Los bloqueos esporádicos son el caso más difícil, porque cuando vas a mirar ya han desaparecido. El caso de estudio del libro es un servidor que rechazaba conexiones durante segundos o minutos cada uno o dos días. El método se puede generalizar:

  • Reúne contexto primero: versiones, motor, hardware, cambios recientes. Idealmente, nadie ha "probado cosas" todavía.
  • Dispara la captura con un síntoma. Vigila un contador que se dispare durante el incidente (en ese caso, Threads_connected saltando de decenas a cientos) y captúralo todo cuando salte.
  • Desconfía de la respuesta conocida. Las escrituras intensas en disco parecían un bug de volcado conocido; los contadores de volcado decían otra cosa.
  • Sigue la evidencia fuera de la base de datos. La causa real era una caché de la aplicación que expiraba y todos los servidores de aplicación reconstruyéndola a la vez: una estampida de caché (cache stampede). El logging a nivel de aplicación lo habría mostrado de inmediato.

Cómo se refleja en QueryCrack

El evaluador es un profiler diminuto: toma una instantánea de los contadores Handler_read_* de la sesión, ejecuta tu consulta y reporta la diferencia. Las filas leídas mediante búsquedas en índice, recorridos de índice y recorridos completos se separan, así que el veredicto no dice solo "demasiado lento", sino qué vía de acceso hizo el daño.

Preguntas frecuentes

¿Es seguro registrar todas las consultas en producción?

Durante periodos cortos, normalmente sí. El coste es sobre todo E/S y espacio en disco. Para tener visibilidad continua, prefiere los digests del Performance Schema, y limita el registro completo con muestreo o con un tiempo acotado.

¿Qué consulta debería optimizar primero?

La que tenga la mayor parte del tiempo total, es decir, frecuencia por coste, no la consulta más lenta que hayas visto.

Fuente: Schwartz, Zaitsev y Tkachenko, High Performance MySQL, capítulo 3: Profiling Server Performance, con notas sobre herramientas actualizadas para MySQL 8. Son nuestras notas, no un sustituto del libro.