한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

Libro blanco del lag en juegos › L12 Base de datos

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)

Abrir la ficha interactiva con gráficos y simulaciones →

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

Síntomas
Input lag, No conecta / carga infinita
Factores
Latencia, Detención
A quién afecta
Solo una función, Todo el servidor
Cuándo
Al hacer ciertas acciones
Responsable
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

  1. How MySQL Uses Indexes MySQL
    Sin índice, se lee toda la tabla desde la primera fila, y cuanto mayor es la tabla, mayor es el costo
  2. Locks Set by Different SQL Statements in InnoDB MySQL
    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
  3. The Slow Query Log MySQL
    Registra las consultas que superan long_query_time (10 s por defecto); también puede registrar aparte las que no usan índice
  4. 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
  5. Statement Summary Tables MySQL
    events_statements_summary_by_digest: SUM_NO_INDEX_USED (veces que se ejecutó sin índice) y SUM_ROWS_EXAMINED por cada forma de consulta
  6. EXPLAIN Output Format MySQL
    type ALL indica un escaneo completo de la tabla, que normalmente se evita añadiendo un índice
  7. The Cumulative Statistics System (PostgreSQL Documentation) PostgreSQL
    seq_scan (número de escaneos secuenciales) y seq_tup_read (filas leídas con escaneos secuenciales) de pg_stat_user_tables
  8. Using EXPLAIN (PostgreSQL Documentation) PostgreSQL
    Seq Scan: plan de ejecución que lee todas las filas de la tabla una tras otra

Ver también

Misma capa: L12 Base de datos

Causas de otras capas con el mismo síntoma (Input lag)

Ver la ficha interactiva con gráficos y simulaciones