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

Optimización de la consulta mysql (me gusta/no me gusta)

En términos de rendimiento, esas subconsultas correlacionadas pueden comerse su almuerzo. Y devora tu fiambrera también, para conjuntos grandes, debido a la forma en que MySQL los procesa. Cada una de esas subconsultas se ejecuta para cada fila devuelta en la consulta externa. Y eso puede ser muy costoso para juegos grandes.

Un enfoque alternativo es usar una vista en línea para materializar los gustos y disgustos de todo el contenido, y luego hacer una operación de unión a eso.

Pero, este enfoque también puede ser costoso, especialmente cuando solo necesita los "recuentos" de votos para unas pocas filas de contenido, de un billón de filas. A menudo, hay un predicado de la consulta externa que también se puede incorporar a la vista en línea, para limitar la cantidad de filas que deben examinarse y devolverse.

Queremos usar una combinación EXTERNA para esa vista en línea, por lo que devuelve un resultado equivalente a su consulta; devolviendo una fila de content cuando no hay filas coincidentes en el vote mesa.

SELECT [... BUNCH OF FIELDS ...]
     , COALESCE(v.likes,0) AS likes
     , COALESCE(v.dislikes,0) AS dislikes
     , COALESCE(v.myvote,'.Constants::NO_VOTE.') AS myvote
  FROM content c
  LEFT
  JOIN ( SELECT vt.cId
              , SUM(vt.vote = '.Constants::LIKE.') AS likes
              , SUM(vt.vote = '.Constants::DISLIKE.') AS dislikes
              , MAX(IF(vt.userId = '.USER_ID.',vt.vote,NULL)) AS myvote
           FROM votes vt
          GROUP
             BY vt.cId
       ) v
    ON v.cId = c.contentId

       [... OTHER STUFF ... ]

Tenga en cuenta que la consulta de vista en línea (con alias v ) va a ver CADA fila de los votes mesa. Si solo necesita un subconjunto, considere agregar un predicado apropiado (ya sea en una cláusula WHERE o como JOIN a otra tabla). No hay ninguna indicación del [... OTHER STUFF ...] en su consulta si está devolviendo solo unas pocas filas de content o si necesita todas las filas porque está ordenando por likes , etc.

Para un pequeño número de filas seleccionadas del content usar las subconsultas correlacionadas (como en su consulta) en realidad puede ser más rápido que materializar una gran vista en línea y realizar una operación de unión contra ella.

Ah... y para ambas consultas, no hace falta decir que un índice apropiado en los votes tabla con una columna inicial de cId beneficiará el rendimiento. Para la vista en línea, no desea que la sobrecarga de MySQL tenga que realizar un filesort operación en todas esas filas para hacer el GROUP BY. Y para las subconsultas correlacionadas, desea que usen un escaneo de rango de índice, no un escaneo completo.