По отношение на производителността, тези корелирани подзаявки могат да ви изядат обяда. И изяжте и вашата кутия за обяд, за големи комплекти, поради начина, по който MySQL ги обработва. Всяка от тези подзаявки се изпълнява за всеки ред, върнат във външната заявка. И това може да излезе много скъпо за големи комплекти.
Алтернативен подход е да използвате вграден изглед, за да материализирате харесванията и нехаресванията за цялото съдържание и след това да извършите операция за присъединяване към това.
Но този подход може да бъде и скъп, особено когато се нуждаете само от „преброяване“ на гласовете само за няколко реда със съдържание от един милион реда. Често има предикат от външната заявка, който също може да бъде включен във вградения изглед, за да се ограничи броят на редовете, които трябва да бъдат прегледани и върнати.
Искаме да използваме ВЪНШНО съединение към този вграден изглед, така че да върне резултат, еквивалентен на вашата заявка; връщане на ред от content
когато няма съвпадащи редове в vote
таблица.
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 ... ]
Имайте предвид, че заявката за вграден изглед (с псевдоним v
) ще разгледа ВСЕКИ ред от votes
маса. Ако имате нужда само от подмножество, помислете за добавяне на подходящ предикат (или в клауза WHERE, или като JOIN към друга таблица). Няма индикация от [... OTHER STUFF ...]
във вашата заявка дали връща само няколко реда от content
или ако имате нужда от всички редове, защото подреждате по likes
и т.н.
За малък брой редове, избрани от content
таблица, използването на корелираните подзаявки (като във вашата заявка) всъщност може да бъде по-бързо от материализирането на огромен вграден изглед и извършването на операция за свързване срещу него.
О... и за двете заявки се разбира, че подходящ индекс на votes
таблица с водеща колона cId
ще бъде от полза за представянето. За вградения изглед не искате излишните разходи на MySQL да извършват filesort
операция върху всички тези редове, за да извършите GROUP BY. А за корелираните подзаявки искате да използват сканиране на диапазон на индекс, а не пълно сканиране.