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

Guia do Lag em Jogos › L12 Banco de dados

Query sem índice Missing index / full table scan

ID da causa db-no-index · Responsável principal Desenvolvimento do servidor (Equipe de desenvolvimento) · Também envolvidos Infraestrutura de banco de dados (Equipe de infraestrutura)

Abrir o card interativo, com figuras e simulações →

Sem índice, para achar as linhas que atendem à condição é preciso ler a tabela inteira (full scan).

Por quê O deploy de um recurso novo adiciona uma busca por uma condição sem índice → Efeito Milhões de linhas são varridas, e uma única query leva de centenas de ms a alguns segundos → Na tela Atraso para carregar a caixa de correio e o histórico de trocas; as conexões ficam presas e outras requisições também esperam

Sintomas
Input lag, Não conecta / loading infinito
Fatores
Latência, Paralisação
Quem é afetado
Só um recurso específico, Servidor inteiro
Quando
Ao fazer ações específicas
Responsável
Responsável principal Desenvolvimento do servidor (Equipe de desenvolvimento) · Também envolvidos Infraestrutura de banco de dados (Equipe de infraestrutura)
O que fazer (Equipe de desenvolvimento)
Revisar o plano de execução das queries novas antes do deploy, adicionar índices, verificar se as queries que alteram dados (UPDATE, DELETE) também usam índice.
O que fazer (Equipe de infraestrutura)
Monitorar o log de queries lentas, encontrar as queries com full scan e compartilhar com a equipe de desenvolvimento, criar índices em produção pelo método online, que segura lock por pouco tempo.
Números de referência
Com índice, alguns ms; sem índice, a query fica mais lenta em proporção ao volume de dados e, em tabelas grandes, chega a ser de centenas a dezenas de milhares de vezes mais lenta.
No gráfico
Degrau a partir de um momento · Latência das queries do BD, linhas lidas
Onde olhar
No MySQL, ver Rows_examined e Rows_sent no slow query log (com log_queries_not_using_indexes ativado, ele também registra queries que não usam índice) e SUM_NO_INDEX_USED e SUM_ROWS_EXAMINED em events_statements_summary_by_digest do performance_schema, e rodar EXPLAIN. No PostgreSQL, ver seq_scan e seq_tup_read em pg_stat_user_tables e rodar EXPLAIN
Confirma se
Uma query que apareceu depois do deploy lê milhares de vezes mais linhas (Rows_examined) do que retorna (Rows_sent), e o EXPLAIN mostra varredura da tabela inteira (MySQL type ALL, PostgreSQL Seq Scan). O seq_tup_read de uma tabela grande cresce rápido a partir do horário do deploy
Descarta se
Usa índice e mesmo assim está lenta: espera por lock (db-hot-row, db-ddl-lock) ou mudança no plano de execução (db-plan-flip). Full scan em tabela pequena pode ser normal
Como verificar
Ferramentas de infra (sem precisar do código do jogo)
Saiba mais
Não são só as leituras que ficam lentas. Dependendo do BD, queries que alteram dados sem índice (UPDATE, DELETE) põem lock até nas linhas varridas e podem bloquear o salvamento de jogadores que não têm nada a ver com elas.

Fontes

  1. How MySQL Uses Indexes MySQL
    Sem índice, o banco lê a tabela inteira a partir da primeira linha, e quanto maior a tabela, maior o custo
  2. Locks Set by Different SQL Statements in InnoDB MySQL
    Se não houver índice adequado e a tabela inteira for varrida, todas as linhas recebem lock e até inserções de outros usuários ficam bloqueadas
  3. The Slow Query Log MySQL
    Registra as queries que passam do long_query_time (padrão de 10 segundos); também é possível registrar à parte as queries que não usam índice
  4. CREATE INDEX (PostgreSQL Documentation) PostgreSQL
    Com CONCURRENTLY, o índice é criado sem bloquear escritas; a criação normal bloqueia escritas até terminar
  5. Statement Summary Tables MySQL
    events_statements_summary_by_digest: por formato de query, SUM_NO_INDEX_USED (vezes em que rodou sem índice) e SUM_ROWS_EXAMINED
  6. EXPLAIN Output Format MySQL
    type ALL indica varredura da tabela inteira, que em geral se evita adicionando um índice
  7. The Cumulative Statistics System (PostgreSQL Documentation) PostgreSQL
    seq_scan (número de varreduras sequenciais) e seq_tup_read (linhas lidas por varredura sequencial) em pg_stat_user_tables
  8. Using EXPLAIN (PostgreSQL Documentation) PostgreSQL
    Seq Scan: plano de execução que lê todas as linhas da tabela em ordem

Veja também

Mesma camada: L12 Banco de dados

Mesmo sintoma (Input lag) em outras camadas

Ver o card interativo, com figuras e simulações