Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Ao ordenar por data desc, o uso temporário torna a consulta mais lenta


Eu acho que a maioria dos problemas aqui e em questões semelhantes vem do mal-entendido de como o MySQL (e outros bancos de dados) usa índices para classificação. A resposta é:o MySQL não usa índices para ordenação, apenas pode ler dados na ordem de um índice ou na direção oposta. Se você quiser que os dados sejam ordenados na ordem do índice atualmente usado - você tem sorte, caso contrário, o resultado será classificado (portanto, filesort em EXPLAIN)

Essa ordem de todo o resultado depende principalmente de qual tabela foi a primeira na junção. E se você olhar para o seu EXPLAIN verá que o join começa na tabela 'log_codes' (porque é muito menor).

Basicamente, o que você precisa é de um índice composto (partner_id, date) em 'log_entries', um índice composto de cobertura (log_code, category_overview, log_desc) para 'log_codes', altere 'INNER JOIN' para 'STRAIGHT_JOIN' para forçar a ordem de junção, e ordenar por 'data' DESC (este índice, felizmente, também cobrirá).

UPD1 :Desculpe, digitei errado o índice da primeira tabela:deve ser (partner_id, log_code, date) .

O MySQL pode produzir dados diretamente, desde que você concorde com a ordem em que os obtém, ou colocar os dados em uma tabela temporária, aplicar a classificação e a saída. Quando você ordena por um campo de qualquer tabela que não seja a primeira em junções, o MySQL precisa classificar os dados (não apenas a saída na ordem de um índice) e, para classificar os dados, ele precisa de uma tabela temporária.

Para gerar as linhas 50.000,25, o MySQL precisa buscar as primeiras 50.000 e ignorá-las. Como eu perdi uma coluna no índice, o MySQL não apenas escaneou o índice, mas para cada item fez uma pesquisa adicional no disco para log_code valor. Com o índice de cobertura que deve ser muito mais rápido, pois todos os dados podem ser buscados no índice.

UPD2 :tente forçar o índice:
SELECT log_entries.date, log_codes.log_desc
FROM log_entries FORCE INDEX (IX_partner_code_date)
STRAIGHT_JOIN log_codes
  ON log_codes.log_code = log_entries.log_code
WHERE log_entries.partner_id = 1
  AND log_codes.category_overview = 1
ORDER BY log_entries.date DESC;