Jeśli chodzi o wydajność, te skorelowane podzapytania mogą zjeść obiad. Pochłoń też swoje pudełko śniadaniowe, w przypadku dużych zestawów, ze względu na sposób, w jaki MySQL je przetwarza. Każde z tych podzapytań jest wykonywane dla każdego wiersza zwróconego w zapytaniu zewnętrznym. A to może być bardzo drogie w przypadku dużych zestawów.
Alternatywnym podejściem jest użycie widoku wbudowanego w celu zmaterializowania upodobań i niechęci do wszystkich treści, a następnie wykonanie operacji łączenia.
Ale to podejście może być również kosztowne, szczególnie gdy potrzebujesz tylko „liczy się” głosów dla zaledwie kilku wierszy treści, z miliarda wierszy. Często istnieje predykat z zapytania zewnętrznego, który można również włączyć do widoku wbudowanego, aby ograniczyć liczbę wierszy, które należy zbadać i zwrócić.
Chcemy użyć sprzężenia OUTER do tego wbudowanego widoku, więc zwraca on wynik odpowiadający zapytaniu; zwracanie wiersza z content
gdy nie ma pasujących wierszy w vote
tabela.
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 ... ]
Zwróć uwagę, że zapytanie wbudowanego widoku (z aliasem v
) przyjrzy się KAŻDEMU wierszowi z votes
stół. Jeśli potrzebujesz tylko podzbioru, rozważ dodanie odpowiedniego predykatu (w klauzuli WHERE lub jako JOIN do innej tabeli). Brak wskazania z [... OTHER STUFF ...]
w zapytaniu, czy zwraca tylko kilka wierszy z content
lub jeśli potrzebujesz wszystkich wierszy, ponieważ zamawiasz według likes
itp.
Dla małej liczby wierszy wybranych z content
tabeli, użycie skorelowanych podzapytań (jak w zapytaniu) może być w rzeczywistości szybsze niż zmaterializowanie ogromnego widoku wbudowanego i wykonanie wobec niego operacji łączenia.
Aha... i dla obu zapytań, jest rzeczą oczywistą, że odpowiedni indeks na votes
tabela z wiodącą kolumną cId
poprawi wydajność. W przypadku widoku wbudowanego nie chcesz, aby obciążenie MySQL wymagało wykonywania filesort
na wszystkich tych wierszach wykonać operację GROUP BY. A dla skorelowanych podzapytań chcesz, aby używały skanowania zakresu indeksów, a nie pełnego skanowania.