использовать u.id, u.username
оба столбца в группе по
SELECT u.id, u.username, COUNT(a.id) AS total_articles,
COUNT(c.id) AS total_comments FROM users u
LEFT JOIN articles a ON u.id = a.user_id
LEFT JOIN comments c ON a.id = c.article_id
GROUP BY u.id, u.username
Если Вы думаете, что реализацией ЛЕВОГО СОЕДИНЕНИЯ является ВНУТРЕННЕЕ ОБЪЕДИНЕНИЕ + больше работы, то этот результат сбивает с толку. Что, если реализация ВНУТРЕННЕГО ОБЪЕДИНЕНИЯ (ОСТАВЛЕНА СОЕДИНЕНИЕ + фильтрующий)? А-ч, это ясно теперь.
В планах запросов, единственная разница - это: пользователи... дополнительные: использование, где . Это означает фильтровать. Существует дополнительный шаг фильтрации в запросе с внутренним объединением.
<час>Это - другой вид фильтрации, чем обычно используется в где пункт. Просто создать индекс на для поддержки этого действия фильтрации.
SELECT *
FROM A
WHERE A.ID = 3
Рассматривают этот запрос:
SELECT *
FROM A
LEFT JOIN B
ON A.ID = B.ID
WHERE B.ID is not null
Этот запрос эквивалентен внутреннему объединению. Нет никакого индекса на B, который поможет тому действию фильтрации. Причина состоит в том, что, где в пункте говорится условие на результате соединения вместо условия на B.
Это происходит, вероятно, из-за ВНУТРЕННЕГО ОБЪЕДИНЕНИЯ, имеющего необходимость проверять каждую строку в обе таблицы, чтобы видеть, соответствуют ли значения столбцов (электронная почта в Вашем случае). ПОКИНУТАЯ JOIN возвратит все из одной таблицы независимо. Если это будет индексировано тогда, то это будет знать, что сделать быстрее также.
imo Вы попадаете в ловушку, известную как преждевременная оптимизация. Оптимизаторы запросов являются безумно непостоянными вещами. Мое предложение, должен идти дальше, пока Вы не можете определить наверняка, что конкретное соединение проблематично.
ПОКИНУТАЯ JOIN возвращает больше строк, чем ВНУТРЕННЕЕ ОБЪЕДИНЕНИЕ, потому что эти 2 отличаются.
, Если ЛЕВОЕ СОЕДИНЕНИЕ не находит связанную запись в таблице, это ищет, это возвратится, АННУЛИРУЕТ для таблицы.
, Но если ВНУТРЕННЕЕ ОБЪЕДИНЕНИЕ не находит связанную запись, оно не возвратится целый строка вообще.
, Но к Вашему вопросу, у Вас есть query_cache включенным? Попытайтесь выполнить запрос с
SELECT SQL_NO_CACHE `contacts`.*, ...
, Кроме которого, я заполнил бы таблицы с большим количеством данных, работал
ANALYZE TABLE t1, t2;
OPTIMIZE TABLE t1, t2;
, И посмотрите то, что происходит.
Try this:
SELECT `contacts`.*, `lists`.`name` AS `group`, `lists`.`id` AS `group_id`, `lists`.`shared_yn`, `tags`.`name` AS `context`, `tags`.`id` AS `context_id`, `tags`.`color` AS `context_color`, `users`.`id` AS `user_id`, `users`.`avatar`
FROM `contacts`
INNER JOIN `users` ON contacts.user_id='1' AND users.email=contacts.email
LEFT JOIN `lists` ON lists.id=contacts.list_id
LEFT JOIN `lists_to_users` ON lists_to_users.user_id='1' AND lists_to_users.creator='1' AND lists_to_users.list_id=lists.id
LEFT JOIN `tags` ON tags.id=lists_to_users.tag_id
ORDER BY `contacts`.`name` ASC
That should give you an extra performance because:
If you don't find any performance improvement, then replace all the columnset for a "COUNT(*)" and do your left/inner tests. This way, regardless of the query, you will retrieve only 1 single row with 1 single column (the count), so you can discard that the number of returned bytes is the cause of the slowness of your query:
SELECT COUNT(*)
FROM `contacts`
INNER JOIN `users` ON contacts.user_id='1' AND users.email=contacts.email
LEFT JOIN `lists` ON lists.id=contacts.list_id
LEFT JOIN `lists_to_users` ON lists_to_users.user_id='1' AND lists_to_users.creator='1' AND lists_to_users.list_id=lists.id
LEFT JOIN `tags` ON tags.id=lists_to_users.tag_id
Good luck
Кардинальность таблицы имеет влияние на оптимизатор запросов. Я предполагаю маленькие таблицы, как Вы имеете, делают внутреннее объединение более сложной операцией. Как только у Вас есть больше записей, чем сервер БД готов сохранить в памяти, внутреннее объединение, вероятно, начнет превосходить левое соединение по характеристикам.