Оставленное Соединение, превосходящее Внутреннее объединение по характеристикам?

использовать 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
15
задан Eran Galperin 9 October 2008 в 18:16
поделиться

6 ответов

Если Вы думаете, что реализацией ЛЕВОГО СОЕДИНЕНИЯ является ВНУТРЕННЕЕ ОБЪЕДИНЕНИЕ + больше работы, то этот результат сбивает с толку. Что, если реализация ВНУТРЕННЕГО ОБЪЕДИНЕНИЯ (ОСТАВЛЕНА СОЕДИНЕНИЕ + фильтрующий)? А-ч, это ясно теперь.

В планах запросов, единственная разница - это: пользователи... дополнительные: использование, где . Это означает фильтровать. Существует дополнительный шаг фильтрации в запросе с внутренним объединением.

<час>

Это - другой вид фильтрации, чем обычно используется в где пункт. Просто создать индекс на для поддержки этого действия фильтрации.

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.

12
ответ дан 1 December 2019 в 03:35
поделиться

Это происходит, вероятно, из-за ВНУТРЕННЕГО ОБЪЕДИНЕНИЯ, имеющего необходимость проверять каждую строку в обе таблицы, чтобы видеть, соответствуют ли значения столбцов (электронная почта в Вашем случае). ПОКИНУТАЯ JOIN возвратит все из одной таблицы независимо. Если это будет индексировано тогда, то это будет знать, что сделать быстрее также.

6
ответ дан 1 December 2019 в 03:35
поделиться

imo Вы попадаете в ловушку, известную как преждевременная оптимизация. Оптимизаторы запросов являются безумно непостоянными вещами. Мое предложение, должен идти дальше, пока Вы не можете определить наверняка, что конкретное соединение проблематично.

2
ответ дан 1 December 2019 в 03:35
поделиться

ПОКИНУТАЯ JOIN возвращает больше строк, чем ВНУТРЕННЕЕ ОБЪЕДИНЕНИЕ, потому что эти 2 отличаются.
, Если ЛЕВОЕ СОЕДИНЕНИЕ не находит связанную запись в таблице, это ищет, это возвратится, АННУЛИРУЕТ для таблицы.
, Но если ВНУТРЕННЕЕ ОБЪЕДИНЕНИЕ не находит связанную запись, оно не возвратится целый строка вообще.

, Но к Вашему вопросу, у Вас есть query_cache включенным? Попытайтесь выполнить запрос с

SELECT SQL_NO_CACHE `contacts`.*, ...

, Кроме которого, я заполнил бы таблицы с большим количеством данных, работал

ANALYZE TABLE t1, t2;
OPTIMIZE TABLE t1, t2;

, И посмотрите то, что происходит.

-3
ответ дан 1 December 2019 в 03:35
поделиться

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:

  • You put all the inner joins before any "left" or "right" join appears. This filters out some records before applying the subsequent outer joins
  • The short-circuit of the "AND" operators (order of the "AND" matters). If the comparition between the columns and the literals is false, it won't execute the required table scan for the comparition between the tables PKs and FKs

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

0
ответ дан 1 December 2019 в 03:35
поделиться

Кардинальность таблицы имеет влияние на оптимизатор запросов. Я предполагаю маленькие таблицы, как Вы имеете, делают внутреннее объединение более сложной операцией. Как только у Вас есть больше записей, чем сервер БД готов сохранить в памяти, внутреннее объединение, вероятно, начнет превосходить левое соединение по характеристикам.

4
ответ дан 1 December 2019 в 03:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: