2009-12-05 1 views
4

Я много читал о реляционных базах данных, используя множество операторов JOIN для каждого SELECT. Тем не менее, я задавался вопросом, есть ли какая-либо проблема с производительностью в долгосрочной перспективе при злоупотреблении этим методом.MySQL ПРИСОЕДИНИТЬ ЗЛОУПОТРЕБИТЬ? Как это плохо получается?

Например, скажем, у нас есть таблица users. Обычно я добавляю «самые используемые» данные, вместо того, чтобы делать какие-либо дополнительные JOIN. Когда я говорю, что «наиболее используемые» данные, например, будут именем пользователя, отображаемым изображением и местоположением.

Эти данные всегда понадобятся при отображении любого пользовательского взаимодействия на веб-сайте, например: на каждой таблице comments JOIN для articles. Вместо того, чтобы делать JOIN на таблицах users & users_profiles, чтобы получить «местоположение» и «отображение», просто используйте информацию на таблице users.

Это мой подход, однако я знаю, что есть много отличных и опытных программистов, которые могут дать мне слово совета по этому вопросу.

Мои вопросы:

Если я пытаюсь быть консервативным с стыки? или я должен использовать их больше? Зачем?

Есть ли проблемы с производительностью в долгосрочной перспективе при многократном использовании JOIN?

Примечание: Я должен уточнить, что я вообще не пытаюсь избежать СОЕДИНЕНИЙ. Я использую их только тогда, когда это необходимо. В этом примере могут быть авторы комментариев/статей, дополнительная информация профиля, которая отображается только на страницах пользовательских профилей ... и т. Д.

+0

Я бы просто хотел, чтобы Клетус ответил на этот вопрос. Его ответы просто превосходны и хорошо развиты. Надеюсь, кто-то сможет ответить более чем в 4 строках. – MarioRicalde

ответ

8

Мой совет по моделированию данных является:

  • Вы должны благоприятствовать факультативные (Nullable) колонны через 1: 1 присоединяется вообще говоря. Есть еще примеры, когда 1: 1 имеет смысл, обычно вращающийся вокруг подтипов. Люди склонны быть более брезгливыми, когда речь идет о столбцах с нулевым значением, чем странно;
  • Не делайте модель тоже непрямой, если действительно обосновано (подробнее об этом ниже);
  • Преимущество объединения на агрегацию. Это может варьироваться, поэтому его необходимо протестировать. См. Пример Oracle vs MySQL vs SQL Server: Aggregation vs Joins;
  • Соединения лучше, чем N + 1.Выбор N + 1 - это, например, выбор порядка из таблицы базы данных, а затем выдача отдельного запроса для получения всех позиций для этого заказа;
  • Масштабируемость объединений обычно только проблема, когда вы делаете массовый выбор. Если вы выберете одну строку, а затем присоедините ее к нескольким вещам, редко это проблема (но иногда это так);
  • Иностранные ключи должны всегда указывать, если вы не имеете дело с тривиально маленькой таблицей;

Подробнее в Database Development Mistakes Made by AppDevelopers.

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

  • Alias ​​(id, username, user_id);
  • Пользователь (id, ...);
  • Адрес электронной почты (id, user_id, адрес электронной почты);
  • Login (id, user_id, ...)
  • Login Роли (id, login_id, role_id);
  • Роль (id, название);
  • Роль Привилегия (id, role_id, privilege_id);
  • Привилегия (id, наименование).

Для этого требуется 6 объединений, чтобы получить от имени пользователя, введенного в фактические привилегии. Конечно, для этого может потребоваться фактическое требование, но чаще всего эта система возникает из-за того, что некоторые разработчики считают, что они могут когда-нибудь понадобиться, хотя каждый пользователь имеет только один псевдоним, пользователь для входа в систему - 1 : 1 и так далее. Более простое решение:

  • пользователя (идентификатор, имя пользователя, адрес электронной почты, тип пользователя)

и, ну, это все. Возможно, если вам нужна сложная система ролей, но также вполне возможно, что вы этого не сделаете, и если вы делаете это достаточно легко для слота (пользовательский тип становится внешним ключом в таблице типов пользователей или ролей), или, как правило, просто для сопоставления от старого до нового.

Это сложная задача: ее легко добавить и удалить трудно. Обычно это постоянное бдение против непреднамеренной сложности, что достаточно плохо, если вы не сделаете это хуже, добавив излишнюю сложность.

+0

Отличный комментарий о сложности: «его легко добавить и удалить сложно» – carl

+0

Большое спасибо за этот отличный ответ. Он отвечает на все мои сомнения по этому поводу. Благодарю. – MarioRicalde

0

Если данные 1 < -> 1, и у вас не будет много нулевых полей, нормализуется. Вы можете указать необходимые поля («наиболее используемые данные») в операторах выбора.

5

Некоторые светлый человек однажды сказал:

Normalize, пока не болит, денормализовать, пока он не работает!

Все зависит от типа объединений и условий соединения, но с ними нет ничего плохого. Входит в таблицу table1.PK = table2.FK очень эффективно.

0

Страх не присоединение. Реляционная модель сильная, и вы должны ее использовать. Кто-то всегда обсуждал N + 1, но также учитывал - в вашем контексте - одновременное соединение с пользователями в целях безопасности, так как запрос может дополнительно указывать на существование пользователя, состояние, правильность сеанса и ожидание поля.

Многие крупные сайты заходят так далеко, чтобы иметь таблицу сеанса и http-таблицу запроса для каждого запроса, всегда соединенную друг с другом для запросов к странице. Преимущество состоит в том, что параметры всегда сопоставляются с сеансами, сеансами для соответствующих пользователей, всегда проверяется статус пользователя, & c & c, но более то, что он позволяет получить некоторые интересные преимущества.

Длинная история, делайте это с умом, но не экономьте на присоединении.

0

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

Даже в самых больших запросах они обычно не являются проблемами производительности - и часто устраняют проблемы с производительностью, которые могут возникнуть, если у вас есть избыточные и повторяющиеся данные повсюду.

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

  • прогулка по всем значениям на левую таблицу, а затем сопоставить их по одному к значениям справа?
  • Как раз наоборот?
  • Отсортируйте ключи из обоих столов и пройдите через них в одно и то же время?
  • Сборка хэшей ключей с обеих сторон?
  • Применить критерии фильтрации до или после данного соединения?
  • и т.д.

Таким образом, если ваш присоединяется сложны в конечном счете, эффективность будет зависеть от сложности вашего оптимизатора/планировщик и валюты и детали вашей статистики. MySQL здесь не является сильным соперником, поэтому я обычно поддерживаю мою модель и sql немного проще, чем если бы я использовал что-то еще. Но несколько подключений к запросу всегда должны быть в порядке.

Смежные вопросы