sql >> Base de Datos >  >> RDS >> Mysql

Al ordenar por fecha de descripción, el uso de consultas temporales ralentiza

Creo que la mayoría de los problemas aquí y en preguntas similares provienen de un malentendido sobre cómo MySQL (y otras bases de datos) usan índices para ordenar. La respuesta es:MySQL no usa índices para ordenar, solo puede leer datos en el orden de un índice o en la dirección opuesta. Si desea que los datos se ordenen en el orden del índice utilizado actualmente, tiene suerte, de lo contrario, el resultado se ordenará (por lo tanto, filesort en EXPLAIN)

Ese orden de todo el resultado depende principalmente de qué tabla fue la primera en la combinación. Y si observa su EXPLAIN, verá que la combinación comienza desde la tabla 'log_codes' (porque es mucho más pequeña).

Básicamente, lo que necesita es un índice compuesto (partner_id, fecha) en 'log_entries', un índice compuesto que cubra (log_code, category_overview, log_desc) para 'log_codes', cambie 'INNER JOIN' a 'STRAIGHT_JOIN' para forzar el orden de unión, y ordenar por 'fecha' DESC (este índice afortunadamente cubrirá también).

UPD1 :Lo siento, escribí mal el índice de la primera tabla:debería ser (partner_id, log_code, date) .

MySQL puede generar datos directamente siempre que esté de acuerdo con el orden en que los obtiene, o puede colocar datos en una tabla temporal, aplicar la ordenación y la salida en ese momento. Cuando ordena por un campo de cualquier tabla que no sea la primera en uniones, MySQL tiene que ordenar los datos (no solo generarlos en el orden de un índice) y para ordenar los datos necesita una tabla temporal.

Para generar filas 50000,25, MySQL de todos modos necesita buscar los primeros 50000 y omitirlos. Como me perdí una columna en el índice, MySQL no solo analizó el índice, sino que para cada elemento realizó una búsqueda adicional en el disco para log_code valor. Con el índice de cobertura, debería ser mucho más rápido, ya que todos los datos se pueden obtener del índice.

UPD2 :intente forzar el í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;