JOIN или LEFT JOIN продолжают проверять в запросе SELECT? - PullRequest
0 голосов
/ 19 июня 2019

У меня есть запрос JOIN, но мне нужно оптимизировать его для производительности.

Например, в этом запросе:

"SELECT id FROM users WHERE id = :id"

Поскольку в конце запроса нет LIMIT 1, этот запрос на выборку продолжит поиск. Если я добавлю LIMIT 1 в конец этого запроса, он выберет только один и перестанет искать больше.

Вот мой вопрос и запрос:

"SELECT messages.text, users.name
FROM messages
LEFT JOIN users
ON messages.from_id = users.id
WHERE messages.user_id = :user_id"

В части JOIN users ON messages.from_id = users.id, поскольку существует только 1 пользователь с таким идентификатором, будет ли он продолжать поиск после того, как найдет этот запрос? Если да, как я могу его оптимизировать, чтобы он искал только 1 строку?

1 Ответ

1 голос
/ 19 июня 2019
SELECT id FROM users WHERE id = :id

Если на id нет индекса, сканируется вся таблица.

Если на id есть UNIQUE или PRIMARY KEY, будет проверяться только одна строка.

Если есть простой INDEX, он будет сканировать с первого совпадения, пока не найдет id, который не соответствует.

Для этого:

SELECT  m.text, u.name
    FROM  messages AS m
    LEFT JOIN  users AS u  ON m.from_id = u.id
    WHERE  m.user_id = :user_id

Будет выполнено «Соединение с вложенным циклом»:

  1. Найдите в * 1020 вхождения, которые удовлетворяют m.user_id = :user_id (см. Выше).
  2. Для каждоготакой строки, достигните users на основе предложения ON.
  3. Может быть несколько строк (опять же, в зависимости от индекса или его отсутствия).

Итак,на ваш вопрос «как я могу оптимизировать его так, чтобы он выполнял поиск только по 1 строке», ответили:

  • Если может быть только одна строка, объявите ее UNIQUE.
  • Еслииногда бывает больше, чем на INDEX.Но не беспокойтесь о проверке дополнительной строки;это не так дорого.

Вы говорите «только 1 пользователь с таким идентификатором», но не можете указать, какой идентификатор в какой таблице.

Но это не конецистория ...

LEFT JOIN может превратиться в JOIN.В этом случае users может быть первой таблицей для просмотра.Также обратите внимание, что оптимизатор достаточно умен, чтобы вывести, что вы хотите u.id = :user_id.В любом случае, NLJ начнёт с users, затем достигнет messages.Опять же, важны типы индексов.

Пожалуйста, предоставьте SHOW CREATE TABLE для обеих таблиц.Тогда я могу сжать ответ на соответствующие части.Пожалуйста, предоставьте EXPLAIN SELECT ... для подтверждения того, что я говорю.

...