Почему OpenCart использует подзапрос вместо LEFT JOIN?

#mysql #opencart #opencart-3

#mysql — сервер #opencart #opencart-3 #mysql

Вопрос:

Недавно я исследовал исходный код opencart и обнаружил, что вместо LEFT JOIN используются подзапросы.

Opencart v3 посмотрите это в файле admin/model/user/user.php

 $query = "SELECT *, (
        SELECT ug.name 
        FROM `" . DB_PREFIX . "user_group` ug 
        WHERE ug.user_group_id = u.user_group_id
    ) AS user_group
    FROM `" . DB_PREFIX . "user` u
    WHERE u.user_id = '" . (int)$user_id . "'"; 
  

Я бы использовал вот так

 $query = "SELECT u.*, ug.name AS user_group 
    FROM `" . DB_PREFIX . "user` u 
    LEFT JOIN `" . DB_PREFIX . "user_group` ug ON ug.user_group_id = u.user_group_id
    WHERE u.user_id = '" . (int)$user_id . "'";
  

Мой вопрос в том, есть ли какое-либо улучшение производительности с использованием подзапроса в столбце Select? Если да, то каким образом? Если нет, то почему это крупное сообщество использует этот способ?
Также я обнаружил, что они не используют внешние ключи, есть идеи, почему?

Комментарии:

1. «Скалярные подзапросы» применяют мощность, равную 1. Соединение по левому краю потенциально может привести к более высокой (читаемой неправильно) мощности, о которой вы не будете знать.

2. Я боюсь вашего английского. Позвольте мне изучить, и я вернусь к вам

3. Если подзапрос возвращает не более одной строки, вероятно, существенной разницы нет. Они также не используют подготовленные инструкции. Я предполагаю, что код просто очень старый.

4. @TheImpaler «Левое соединение потенциально может привести к увеличению (читается неправильно) мощности, о которой вы не будете знать». что это значит?

5. @TheImpaler что такое неправильно прочитанная мощность? и как это будет выше? Я никогда не слышал об этом. Оба запроса извлекаются из одной и той же таблицы, тогда каким может быть результат «неправильного чтения»?

Ответ №1:

Коррелированный подзапрос может стать проблемой производительности, когда внешний запрос обрабатывает большое количество строк; потому что подзапрос выполняется для каждой строки.

Похоже, что этот запрос возвращает не более одной строки, потому что похоже, что user_id это уникальный ключ. Поскольку внешний запрос возвращает (максимум) одну строку, подзапрос будет выполнен только один раз.

Также похоже, что user_group_id это уникальный ключ в user_group таблице, так что подзапрос вернет не более одной строки. (В более общем случае, если подзапрос возвращает более одной строки, мы получим ошибку. При соединении по ЛЕВОМУ КРАЮ мы бы вернули несколько строк.)


Вопрос: Есть ли какое-либо улучшение производительности при использовании подзапроса в столбце выбора?

Ответ: снижения производительности ни в одной из форм не будет. Форма с коррелированным подзапросом может быть быстрее, но разница несущественна.

Вопрос: Если да, то каким образом? Если нет, то почему это крупное сообщество использует этот способ?

О: Это допустимый SQL, он работает, и нет никакого стимула вносить изменения.

В: Также я обнаружил, что они не используют внешние ключи, есть идеи, почему?

О: Нет требования, чтобы СУБД обеспечивала ссылочную целостность; если приложение обрабатывает это, то мы можем избежать накладных расходов в базе данных.

Некоторые механизмы хранения (например, MyISAM) не применяют ограничения внешнего ключа.

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


Это все дизайнерские решения; есть несколько способов скинуть кошку. (Здесь мы просто скользим по поверхности; погружение глубже было бы больше основано на мнениях, чтобы привести аргументы в пользу того, какой способ освежевать кошку лучше.)

Комментарии:

1. Так должен ли я использовать коррелированный подзапрос с каждым запросом, который дает результат только в одной строке вместо объединения по левому краю? Или я должен придерживаться left joins для запроса одной строки?

2. По моему опыту, коррелированные подзапросы обычно имеют худшую производительность. В некоторых случаях они обладают лучшей производительностью, но это, как правило, исключение, а не правило. В случае вашего вопроса версия join, вероятно, быстрее.

3. Файзан … используй тот шаблон, который наиболее подходит. Избегайте коррелированных подзапросов, которые будут выполняться несколько раз. @Uueerdo: По моему опыту, коррелированный подзапрос в списке ВЫБОРА запроса, который возвращает одну строку, поэтому коррелированный подзапрос выполняется один раз при наличии подходящего индекса, существенной разницы в производительности по сравнению с эквивалентным результатом, возвращаемым с помощью JOIN, нет. Когда коррелированные подзапросы выполняются несколько раз, это приводит к снижению производительности.

4. @spencer7593 согласен, коррелированные запросы, выполняемые несколько раз, имеют относительно небольшую стоимость, могут быть проще для понимания и даже могут быть быстрее, когда результаты внешнего запроса относительно малы по сравнению с сопоставляемыми данными.