När det gäller prestanda kan de korrelerade underfrågorna äta din lunch. Och sluka din lunchlåda också, för stora set, på grund av hur MySQL bearbetar dem. Var och en av dessa underfrågor exekveras för varje rad som returneras i den yttre frågan. Och det kan bli väldigt dyrt för stora uppsättningar.
Ett alternativt tillvägagångssätt är att använda en inline-vy för att förverkliga vad som gillas och ogillas för allt innehåll och sedan göra en kopplingsoperation till det.
Men det här tillvägagångssättet kan också vara dyrt, särskilt när du bara behöver rösten "räknas" för bara några innehållsrader, av en basillion rader. Ofta finns det ett predikat från den yttre frågan som också kan införlivas i inlinevyn, för att begränsa antalet rader som behöver undersökas och returneras.
Vi vill använda en OUTER-koppling till den inline-vyn, så den returnerar ett resultat som motsvarar din fråga; returnera en rad från content
när det inte finns några matchande rader i vote
bord.
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 ... ]
Observera att inline-vyfrågan (alias som v
) kommer att titta på VARJE enskild rad från votes
tabell. Om du bara behöver en delmängd, överväg att lägga till ett lämpligt predikat (antingen i en WHERE-sats eller som en JOIN till en annan tabell). Det finns ingen indikation från [... OTHER STUFF ...]
i din fråga om det bara returnerar några rader från content
eller om du behöver alla rader för att du beställer efter likes
osv.
För ett litet antal rader valda från content
tabell, att använda de korrelerade underfrågorna (som i din fråga) kan faktiskt vara snabbare än att materialisera en enorm inlinevy och utföra en kopplingsoperation mot den.
Åh... och för båda frågorna är det självklart att ett lämpligt index på votes
tabell med en ledande kolumn cId
kommer att gynna prestanda. För inlinevyn vill du inte att overheaden för MySQL måste utföra en filesort
operation på alla dessa rader för att göra GROUP BY. Och för de korrelerade underfrågorna vill du att de ska använda en skanning av indexintervall, inte en fullständig genomsökning.