MySQL ПРИСОЕДИНЯЕТСЯ Насколько это плохо? - PullRequest
5 голосов
/ 05 декабря 2009

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

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

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

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

Мои вопросы:

Должен ли я попытаться быть консервативным с СОЕДИНЕНИЯМИ? или я должен использовать их больше? Почему?

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

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

Ответы [ 5 ]

8 голосов
/ 05 декабря 2009

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

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

Подробнее о Ошибки при разработке баз данных, сделанные AppDevelopers .

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

  • Псевдоним (id, username, user_id);
  • Пользователь (id, ...);
  • E-mail (id, user_id, адрес электронной почты);
  • Логин (id, user_id, ...)
  • Роли входа в систему (id, login_id, role_id);
  • Роль (идентификатор, имя);
  • Привилегия роли (id, role_id, privilege_id);
  • Привилегия (идентификатор, имя).

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

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

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

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

5 голосов
/ 05 декабря 2009

Какой-то яркий человек однажды сказал:

Нормализуй, пока не болит, денормализуй, пока не заработает!

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

1 голос
/ 05 декабря 2009

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

0 голосов
/ 07 декабря 2009

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

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

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

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

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

0 голосов
/ 06 декабря 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...