Это хороший вопрос, но я хотел бы также добавить третий вариант (более стандартный способ сделать это):
select t.id, count(c.topic_id) as count
from topic left join
comment c
on t.id = c.topic_id
group by t.id;
Первый способ часто является наиболее эффективным в MySQL , MySQL может использовать индекс для comment(topic_id)
для генерации счета. Это может быть справедливо и в других базах данных, но это особенно заметно в MySQL, который не использует индексы для group by
на практике.
Второй запрос представляет собой агрегацию, а затем соединение. Подзапрос материализуется, добавляя дополнительные служебные данные, а затем join
не может использовать индекс на comment
. Он мог бы использовать индекс на topic
, но left join
может сделать этот вариант менее вероятным. (Вам нужно будет проверить план выполнения в вашей среде.)
Третий вариант будет эквивалентен первому во многих базах данных, но не в MySQL. Он присоединяется к comment
(используя индекс по comment(topic_id)
, если таковой имеется). Тем не менее, он затем несет накладные расходы на сортировку файлов для окончательной агрегации.
Неохотно, я должен признать, что первый выбор часто является лучшим с точки зрения производительности в MySQL, особенно если доступны нужные индексы. Без индексов любой из трех вариантов может быть лучшим выбором. Например, без индексов второй является лучшим, если comments
пуст или имеет очень мало тем.
Ваш второй пример - соединение с производной таблицей. Преимущество - это производная таблица генерируется один раз, устанавливается на основе. Первые коррелированные риски подзапроса выполняются один раз в строке таблицы «topic» – StuartLC
Итак, вы имеете в виду, что подзапрос подходит для извлечения одной записи? и второй для списка регрессирования? – reverbnation
@reverbnation, если вы хотите задать вопрос из StuartLC, вы должны называть его '@' –