Wat de prestaties betreft, kunnen die gecorreleerde subquery's uw lunch opeten. En verslind ook je lunchbox, voor grote sets, vanwege de manier waarop MySQL ze verwerkt. Elk van die subquery's wordt uitgevoerd voor elke rij die wordt geretourneerd in de buitenste query. En dat kan erg duur worden voor grote sets.
Een alternatieve benadering is om een inline-weergave te gebruiken om de sympathieën en antipathieën voor alle inhoud te concretiseren, en daar vervolgens een samenvoegbewerking op uit te voeren.
Maar deze aanpak kan ook duur zijn, vooral als je de stemmen maar nodig hebt voor slechts een paar inhoudsrijen, uit een biljoen rijen. Vaak is er een predikaat uit de buitenste query dat ook kan worden opgenomen in de inline-weergave, om het aantal rijen te beperken dat moet worden onderzocht en geretourneerd.
We willen een OUTER-join gebruiken voor die inline-weergave, dus het retourneert een resultaat dat gelijk is aan uw zoekopdracht; een rij retourneren uit content
wanneer er geen overeenkomende rijen zijn in de vote
tafel.
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 ... ]
Merk op dat de inline view-query (alias v
) gaat ELKE rij bekijken van de votes
tafel. Als je alleen een subset nodig hebt, overweeg dan om een geschikt predikaat toe te voegen (in een WHERE-clausule of als JOIN aan een andere tabel). Er is geen indicatie van de [... OTHER STUFF ...]
in uw vraag of het slechts een paar rijen retourneert van content
of als je alle rijen nodig hebt omdat je bestelt op likes
, enz.
Voor een klein aantal rijen geselecteerd uit de content
tabel, kan het gebruik van de gecorreleerde subquery's (zoals in uw query) zelfs sneller zijn dan het realiseren van een enorme inline-weergave en het uitvoeren van een join-bewerking ertegen.
Oh... en voor beide zoekopdrachten is het vanzelfsprekend dat een geschikte index op de votes
tabel met een leidende kolom van cId
zal de prestaties ten goede komen. Voor de inline-weergave wilt u niet dat de overhead van MySQL een filesort
moet uitvoeren bewerking op al die rijen om de GROUP BY. En voor de gecorreleerde subquery's wilt u dat ze een indexbereikscan gebruiken, geen volledige scan.