Med hensyn til ydeevne kan disse korrelerede underforespørgsler spise din frokost. Og spis også din madpakke til store sæt på grund af den måde, MySQL behandler dem på. Hver af disse underforespørgsler udføres for hver række, der returneres i den ydre forespørgsel. Og det kan blive meget dyrt for store sæt.
En alternativ tilgang er at bruge en inline-visning til at materialisere likes og dislikes for alt indhold, og derefter udføre en join-operation til det.
Men denne tilgang kan også være dyr, især når du kun har brug for at stemme "tæller" for blot nogle få indholdsrækker ud af en bazillion rækker. Ofte er der et prædikat fra den ydre forespørgsel, som også kan inkorporeres i inline-visningen, for at begrænse antallet af rækker, der skal undersøges og returneres.
Vi ønsker at bruge en OUTER join til den inline-visning, så den returnerer et resultat svarende til din forespørgsel; returnerer en række fra content
når der ikke er nogen matchende rækker i vote
tabel.
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 ... ]
Bemærk, at den inline-visningsforespørgsel (aliasset som v
) kommer til at se på HVER enkelt række fra votes
bord. Hvis du kun har brug for en delmængde, så overvej at tilføje et passende prædikat (enten i en WHERE-sætning eller som en JOIN til en anden tabel). Der er ingen indikation fra [... OTHER STUFF ...]
i din forespørgsel, om det kun returnerer nogle få rækker fra content
eller hvis du har brug for alle rækkerne, fordi du bestiller efter likes
osv.
For et lille antal rækker valgt fra content
tabel, kan det faktisk være hurtigere at bruge de korrelerede underforespørgsler (som i din forespørgsel) end at realisere en enorm indlejret visning og udføre en joinoperation mod den.
Åh... og for begge forespørgsler siger det sig selv, at et passende indeks på votes
tabel med en ledende kolonne af cId
vil gavne ydeevnen. Til inline-visningen ønsker du ikke, at overhead af MySQL skal udføre en filesort
handling på alle disse rækker for at udføre GROUP BY. Og for de korrelerede underforespørgsler vil du have, at de skal bruge en indeksområdescanning, ikke en fuld scanning.