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.