Consultas sin índice Missing index / full table scan
ID de la causa db-no-index · Responsable principal Desarrollo de servidor (Equipo de desarrollo) · También Infraestructura de BD (Equipo de infraestructura)
Sin índice, encontrar las filas que cumplen una condición obliga a leer la tabla entera (escaneo completo).
Por qué Un despliegue con una función nueva añade búsquedas por condiciones sin índice → Efecto Se escanean millones de filas y cada consulta tarda de cientos de ms a varios segundos → En pantalla El buzón y el historial de intercambios tardan en cargar, y como las conexiones quedan ocupadas, otras solicitudes también esperan
Responsable principal Desarrollo de servidor (Equipo de desarrollo) · También Infraestructura de BD (Equipo de infraestructura)
Tareas (Equipo de desarrollo)
Revisar el plan de ejecución de las consultas nuevas antes del despliegue, añadir índices, comprobar que también las consultas que modifican datos (UPDATE, DELETE) usan índice.
Tareas (Equipo de infraestructura)
Vigilar el log de consultas lentas, localizar las consultas con escaneo completo y compartirlas con el equipo de desarrollo, crear los índices en producción con el método online, que bloquea poco tiempo.
Cifras de referencia
Con índice tarda unos pocos ms; sin él, se vuelve más lenta en proporción al tamaño de los datos, y en tablas grandes puede ser de cientos a decenas de miles de veces más lenta.
En el gráfico
Salto en escalón · Latencia de las consultas a la BD, filas leídas
Dónde mirar
En MySQL, Rows_examined y Rows_sent del slow query log (con log_queries_not_using_indexes activado también registra las consultas que no usan índice), SUM_NO_INDEX_USED y SUM_ROWS_EXAMINED de events_statements_summary_by_digest en performance_schema, y ejecutar EXPLAIN. En PostgreSQL, seq_scan y seq_tup_read de pg_stat_user_tables, y ejecutar EXPLAIN
Se confirma si
Una consulta que apareció tras el despliegue lee miles de veces más filas (Rows_examined) de las que devuelve (Rows_sent), y EXPLAIN muestra un escaneo completo de la tabla (type ALL en MySQL, Seq Scan en PostgreSQL). El seq_tup_read de una tabla grande crece bruscamente desde la hora del despliegue
Se descarta si
Si usa índice y aun así va lenta, apunta a esperas por bloqueos (db-hot-row, db-ddl-lock) o a un cambio del plan de ejecución (db-plan-flip). Un escaneo completo de una tabla pequeña puede ser normal
Se verifica con
Con herramientas de infraestructura (no hace falta código del juego)
Para saber más
El problema va más allá de las lecturas lentas. Según la BD, una consulta que modifica datos sin índice (UPDATE, DELETE) bloquea también las filas que escanea, y puede llegar a frenar los guardados de jugadores que no tienen nada que ver.
Fuentes
How MySQL Uses IndexesMySQL Sin índice, se lee toda la tabla desde la primera fila, y cuanto mayor es la tabla, mayor es el costo
Locks Set by Different SQL Statements in InnoDBMySQL Si no hay un índice adecuado y se escanea toda la tabla, se bloquean todas las filas, y hasta las inserciones de otros usuarios quedan bloqueadas
The Slow Query LogMySQL Registra las consultas que superan long_query_time (10 s por defecto); también puede registrar aparte las que no usan índice
CREATE INDEX (PostgreSQL Documentation)PostgreSQL Con CONCURRENTLY, el índice se crea sin bloquear las escrituras; la creación normal bloquea las escrituras hasta que termina
Statement Summary TablesMySQL events_statements_summary_by_digest: SUM_NO_INDEX_USED (veces que se ejecutó sin índice) y SUM_ROWS_EXAMINED por cada forma de consulta
EXPLAIN Output FormatMySQL type ALL indica un escaneo completo de la tabla, que normalmente se evita añadiendo un índice