Таблица составлена ​​исключительно из внешних ключей?

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

Изучая базу данных, мне понадобится что-то вроде таблицы "Членство":

UserID|GroupID
------|-------
  1   |   1
  1   |   2
  2   |   1
  2   |   3
  2   |   5

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

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

Спасибо.

2 ответа

Решение

Это стандартный способ представления отношения "многие ко многим", известный как "таблица соединений" (или "таблица ссылок").

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

  1. Сделать составной (первичный) ключ на {UserID, GroupID}, Помимо того, что один и тот же пользователь не может быть подключен к одной и той же группе несколько раз, это также способствует эффективному поиску групп данного пользователя. Поскольку UserID находится на переднем крае индекса (который СУБД автоматически создает под ключом), все значения GroupID, связанные с одним и тем же UserID, находятся в непрерывном диапазоне в B-дереве индекса, поэтому можно получить группы данного пользователя. выполняется СУБД путем простого сканирования диапазона индекса.
  2. Сделать составной (первичный) ключ на {GroupID, UserID}, Те же поля, в обратном порядке. Это способствует быстрому получению пользователей данной группы (то есть запросы в противоположном "направлении" по сравнению с (1)).
  3. Сделай ключ на {UserID, GroupID} и (уникальный) индекс на {GroupID, UserID} (или наоборот). Это полезно, если вам нужно выполнить запрос в обоих направлениях: получить группы данного пользователя и соответственно получить пользователей данной группы.
  4. Сделайте (1) или (2) или (3) выше, но также сделайте суррогатный ключ (например, {UserGroupID}). Это может быть полезно, если у вас есть "дочерние" таблицы, которые ссылаются на соединительную таблицу, и вы хотите оптимизировать размер ключа, который переносится на них через внешние ключи. Это также может быть полезно, если ваш инструмент ORM плохо работает с составными ключами.

Если вы выбрали варианты (1) или (2), сгруппируйте таблицу (если ваша СУБД поддерживает это). Так как в любом случае вы выполняете только сканирование диапазона индекса, кучи таблиц вообще не требуется. Вы должны даже рассмотреть кластеризацию для (3), так как оба индекса охватывают, поэтому нет опасности двойного поиска.

Этот вид настройки является совершенно обычным и прекрасно работает.

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

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

Вы можете узнать больше о многостолбцовых индексах здесь: http://www.mysqlperformanceblog.com/2009/09/19/multi-column-indexes-vs-index-merge/

а также

http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html

Другие вопросы по тегам