SQL: Вам нужен автоинкрементный первичный ключ для таблиц Many-Many?

Скажем, у вас есть таблица "многие-многие" между артистами и фанатами. Когда дело доходит до проектирования стола, вы проектируете стол следующим образом:

ArtistFans
    ArtistFanID (PK)
    ArtistID (FK)
    UserID (FK)

 (ArtistID and UserID will then be contrained with a Unique Constraint 
  to prevent duplicate data) 

Или вы используете компоновку PK для двух соответствующих полей:

ArtistFans
    ArtistID (PK)
    UserID (PK)

(The need for the separate unique constraint is removed because of the 
 compound PK)

Есть ли какие-либо преимущества (возможно, индексирование?) Для использования прежней схемы?

7 ответов

Решение
ArtistFans
    ArtistID (PK)
    UserID (PK)

Использование автоинкрементного PK здесь не имеет преимуществ, даже если они есть у родительских таблиц.

Я бы также создал индекс "обратный PK" автоматически (UserID, ArtistID) тоже: он вам понадобится, потому что вы будете запрашивать таблицу по обоим столбцам.

Столбцы Autonumber/ID имеют свое место. Вы бы выбрали их для улучшения определенных вещей после процесса нормализации на основе физической платформы. Но не для таблиц ссылок: если ваш ORM мозговой мертвой настаивает, то измените ORM...

Редактировать, октябрь 2012

Важно отметить, что вам все еще нужны уникальные (UserID, ArtistID) а также (ArtistID, UserID) индексов. Добавление автоинкрементов просто занимает больше места (в памяти, а не только на диске), которое не должно использоваться

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

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

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

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

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

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

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

ArtistFans
    ArtistFanId
    ArtistId (PK)
    UserId (PK)

Столбцы идентичности могут быть полезны для связи этого отношения с другими отношениями. Например, если существует таблица создателя, в которой указан человек, создавший отношение художник-пользователь, он может иметь внешний ключ для ArtistFanId вместо составного первичного ключа ArtistId+UserId.

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

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

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

Забавно, что все ответы в пользу варианта 2, поэтому я вынужден выступать против варианта 1;)

Чтобы ответить на вопрос в заголовке: нет, он вам не нужен. Но...

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

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

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

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

Конечно, я должен упомянуть один недостаток: в отношениях дедушка-родитель-ребенок child потеряет информацию своего деда и потребует JOIN для ее получения.

На мой взгляд, в чистом SQL столбец id не является необходимым и не должен использоваться. Но для каркасов ORM, таких как Hibernate, управлять отношениями "многие ко многим" непросто с помощью составных ключей и т. Д., Особенно если в объединяемой таблице есть дополнительные столбцы.

Поэтому, если я собираюсь использовать каркас ORM в БД, я предпочитаю помещать столбец идентификатора с автоинкрементом в эту таблицу и уникальное ограничение для ссылающихся столбцов вместе. И, конечно, не пустое ограничение, если оно требуется.

Затем я отношусь к таблице так же, как к любой другой таблице в моем проекте.

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