2011-12-25 11 views
6

La siguiente consulta es relativamente lento (0,7 segundos con ~ 6k filas)MySQL grupo lenta/ordenado por

SELECT items.*, COUNT(transactions.ID) 
    FROM items 
    INNER JOIN users ON (items.USER = users.ID) 
    LEFT JOIN transactions ON (items.id = transactions.item) 
    WHERE items.ACTIVE = 1 
    AND items.DELETED_AT IS NULL 
    GROUP BY items.ID 
    ORDER BY items.DATE DESC 
    LIMIT 20 

Pero acelera drásticamente cuando es ordenado por items.ID DESC en lugar de items.DATE. Las transacciones se unen a una tabla grande (~ 250k filas) y es uno a muchos. La columna de fecha tiene un índice.

¿Hay alguna manera de mejorar genéricamente el rendimiento de ORDER BY?

EDITAR: índices en items.user, transactions.item y items.date. Los elementos tienen 49 columnas, usuarios 76 y transacciones 17.

+3

¿Puede proporcionar los esquemas y especialmente los índices de las tres tablas? – TetonSig

+0

Lo único que puedo pensar es primero seleccionar elementos filtrados por su cláusula WHERE y ordenados por fecha en una subconsulta, (o en una vista, si MySQL no admite ORDER BY en subconsultas,) y luego en una consulta adjunta do tus uniones. (No estoy escribiendo esto como una respuesta porque SO desalienta las respuestas especulativas.) –

+0

¿Ha intentado incluir 'items.DATE' en' GROUP BY' (en la primera posición también)? –

Respuesta

5

Los índices pueden afectar el rendimiento de las cláusulas ORDER BY. Es probable que este MySQL manual page valga la pena. Esencialmente, si ordena por una columna que es parte del índice que MySQL utiliza para la consulta, MySQL puede usar el índice para la clasificación en lugar de los datos en sí.

En su consulta particular, el hecho de que la columna DATE tenga un índice no importa, ya que ese índice probablemente no se esté utilizando en su consulta. Su instrucción WHERE contiene items.ACTIVE y items.DELETED_AT, y si esas columnas tienen un índice que se usa para el WHERE que no incluye la columna DATE, entonces MySQL no puede usar el índice para ordenar por DATE, y es probable que recurra a un archivo ordenar.

Si puede obtener un índice que pueda ser usado por WHERE y ORDER BY, obtendrá un impulso de optimización. En este caso, items.ACTIVE parece una columna de cardinalidad baja, por lo que suponiendo que items.DELETED_AT es una fecha, probablemente probaría un índice como INDEX(DELETED_AT,DATE) para esa tabla.

Para más información sobre lo que está pasando allí, puede obtener más información.

0

Estas son las cosas que PODRÍA (no se puede leer) ayudar.

  1. Eliminar el * en los elementos. * Y enumere cada campo individualmente. 49 columnas es mucho, ¿realmente las necesita todas?
  2. Por lo general, el motor optimiza las consultas de manera que se considera que se limitan los criterios en las uniones. Quizás el plan utilizado por el motor no está haciendo esto (necesita explicar los resultados del plan para saberlo) así que reorganizando la cláusula where y las uniones MAYO (no probable) ayuda por forzando al motor a considerar esto. (Ver más abajo)
  3. Reconstruir estadísticas de la tabla si muchos de actualización, inserción, elimina tienen ocurrido con el tiempo, es posible que las estadísticas de la tabla están apagados y necesitan ser rebuilt para cada tabla

.

SELECT items.[list fields], COUNT(transactions.ID) 
    FROM items 
    INNER JOIN users ON (items.USER = users.ID) 
     AND items.Active=1 
     AND items.DELETED_AT is Null 
    LEFT JOIN transactions ON (items.id = transactions.item) 
    GROUP BY items.ID 
    ORDER BY items.DATE DESC 
    LIMIT 20 
2

SELECT * FROM (SELECT * FROM wp_users DONDE 1 GRUPO POR límite ID 0,10) como X ORDER BY ID DESC

La consulta anterior funciona perfecto, lo he utilizado en una base de datos muy larga .ORDEN POR el listado de 10 O (xx) elementos que estamos obteniendo de la consulta de selección interna, ¡así que es muy RÁPIDO!