Pregunta

¿Qué más puedo hacer para optimizar esta consulta?

SELECT * FROM
    (SELECT `item`.itemID, COUNT(`votes`.itemID)  AS `votes`,
           `item`.title, `item`.itemTypeID, `item`.
           submitDate, `item`.deleted, `item`.ItemCat,
           `item`.counter, `item`.userID, `users`.name,
           TIMESTAMPDIFF(minute,`submitDate`,NOW()) AS 'timeMin' ,
           `myItems`.userID as userIDFav, `myItems`.deleted as myDeleted
      FROM    (votes `votes` RIGHT OUTER JOIN item `item`
                  ON (`votes`.itemID = `item`.itemID))
           INNER JOIN
              users `users`
           ON (`users`.userID = `item`.userID)
    LEFT OUTER JOIN
              myItems `myItems`
           ON (`myItems`.itemID = `item`.itemID)
     WHERE (`item`.deleted = 0)
     GROUP BY `item`.itemID,
              `votes`.itemID,
              `item`.title,
              `item`.itemTypeID,
              `item`.submitDate,
              `item`.deleted,
              `item`.ItemCat,
              `item`.counter,
              `item`.userID,
              `users`.name,
              `myItems`.deleted,
              `myItems`.userID
    ORDER BY `item`.itemID DESC) as myTable
where myTable.userIDFav = 3 or myTable.userIDFav is null
            limit 0, 20 

Estoy usando MySQL

Gracias

¿Fue útil?

Solución

Por supuesto, como @theomega Dicho esto, a ver el plan de ejecución.

Pero También me sugieren para tratar de "limpiar" su estado de cuenta. (No sé cuál es más rápido -. Eso depende de sus tamaños de la tabla) Por lo general, me gustaría probar a comenzar con una declaración limpio y comenzar a optimizar a partir de ahí. Pero por lo general, una declaración limpia hace que sea más fácil para el optimizador para llegar a un buen plan de ejecución.

Así que aquí están algunas observaciones acerca de su estado de cuenta que podría hacer las cosas con calma:

  • un par de combinaciones externas (hace que sea difícil para el optimzer de averiguar un índice a utilizar)
  • un grupo por
  • una gran cantidad de columnas para agrupar por

Por lo que yo entiendo su SQL, esta declaración debe hacer la mayor parte de lo que está haciendo la suya:

SELECT `item`.itemID, `item`.title, `item`.itemTypeID, `item`.
       submitDate, `item`.deleted, `item`.ItemCat,
       `item`.counter, `item`.userID, `users`.name,
       TIMESTAMPDIFF(minute,`submitDate`,NOW()) AS 'timeMin' 
  FROM    (item `item` INNER JOIN users `users`
       ON (`users`.userID = `item`.userID)

donde

Por supuesto, esto no alcanza la información de las tablas de inscribirse exterior, sugeriría a tratar de añadir las columnas necesarias a través de una subselección:

SELECT `item`.itemID, 
       (SELECT count (itemID)
        FROM votes v
       WHERE v.itemID = 'item'.itemID) as 'votes', <etc.>

De esta manera, usted puede deshacerse de una combinación externa y por el grupo. La combinación externa se sustituye por la subselección, por lo que es una solución de compromiso que puede ser malo para la declaración "más limpia".

En función de la cardinalidad entre este punto y myItems, puede hacer lo mismo o usted tendría que seguir con la combinación externa (pero no hay necesidad de volver a introducir el grupo por).

Espero que esto ayude.

Otros consejos

¿Qué hace el analizador decir de esta búsqueda? Sin el conocimiento acerca de cuántas filas hay en la tabla que no puede decir ninguna optimización. Así que corre el analizador y verá lo que cuesta partes lo.

Algunas reflexiones semi-aleatorias rápidas:

se indexan sus ITEMID y columnas ID de usuario?

¿Qué ocurre si se agrega "explicar" al inicio de la consulta y ejecutarlo? ¿Utiliza índices? ¿Son sensibles?

Qué se necesita para ejecutar toda la consulta interna y el filtro en él, o podría poner mover la parte where myTable.userIDFav = 3 or myTable.userIDFav is null en la consulta interna?

No parecen tener demasiados campos en la lista Agrupar por, ya que uno de ellos es ItemID, sospecho que usted podría utilizar un SELECT interna para preformas de la agrupación y un SELECT externa para devolver el conjunto de campos deseada.

No se puede añadir la cláusula where myTable.userIDFav = 3 o myTable.userIDFav es nulo DONDE (item.deleted = 0) ?

Saludos
Lieven

Mira la forma en que su consulta se construyó. Se une a un montón de cosas, entonces limitar la salida a 20 filas. Usted debe tener la combinación externa en los elementos y myitems, ya que sus condiciones sólo se aplican a estas dos tablas, limitar la salida de las primeras 20 filas, y luego unirse y agregados. Aquí está realizando una gran cantidad de trabajo que va a ser desechada.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top