High Performance MySQL [Cap. 3: Perfilado del rendimiento del servidor]
High Performance MySQL
- 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:
| COLUMNA | SIGNIFICADO |
|---|---|
| Posición | Lugar según su parte del tiempo de respuesta total. |
| Tiempo total | Sumado sobre todas las apariciones de la tarea. |
| Porcentaje | Porcentaje de todo el tiempo medido. |
| Llamadas | Cuántas veces se ejecutó la tarea. |
| Tiempo por llamada | El 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_connectedsaltando 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.