Нужны ли таблицы ссылок бессмысленное поле первичного ключа? - PullRequest
24 голосов
/ 04 декабря 2009

Я работаю над парой таблиц ссылок, и я подумал (Danger Will Robinson, Danger), каковы возможные структуры таблицы ссылок и каковы их плюсы и минусы.

Я придумал несколько возможных ограничений для таблицы ссылок:

Традиционная модель с тремя колоннами

  • id - ПЕРВИЧНЫЙ ПЕРВИЧНЫЙ НОМЕР
  • table1fk - внешний ключ
  • table2fk - внешний ключ

Это классика, в большинстве книг, - сказал Нуфф.

Индексированная модель с 3 столбцами

  • id - ПЕРВИЧНЫЙ ПЕРВИЧНЫЙ НОМЕР
  • table1fk - внешний ключ INDEX ('table1fk')
  • table2fk - внешний ключ INDEX ('table2fk')

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

Композитный ключ 2 столбца ADD PRIMARY KEY ('table1fk' , 'table2fk')

  • table1fk - внешний ключ
  • table2fk - внешний ключ

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

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

Ответы [ 12 ]

18 голосов
/ 04 декабря 2009

Я бы использовал составной ключ, а не лишний бессмысленный ключ.

Я бы не использовал систему ORM, которая применяет такие правила в моей структуре БД.

12 голосов
/ 04 декабря 2009

Для истинных таблиц ссылок они обычно не существуют как объектные объекты в моих объектных моделях. Таким образом, суррогатный ключ никогда не используется. Удаление элемента из коллекции приводит к удалению элемента из отношения ссылки, в котором известны оба внешних ключа (Person.Siblings.Remove(Sibling) или Person.RemoveSibling(Sibling), которые соответствующим образом переводятся на уровне доступа к данным как usp_Person_RemoveSibling(PersonID, SiblingID)).

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

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

6 голосов
/ 14 января 2011

Наличие одного столбца pk может помочь в ситуации аварийного восстановления. Так что, хотя в теории правильно, что вам нужны только 2 внешних ключа. На практике, когда дерьмо попадает в вентилятор, вам может понадобиться один столбец ключа Я никогда не был в ситуации, когда меня ввернули, потому что у меня был идентификатор одного столбца, но я был в тех, где меня ввернули, потому что я этого не сделал.

6 голосов
/ 04 декабря 2009

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

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

3 голосов
/ 04 декабря 2009

Составьте ПК и отключите кластеризацию.

1 голос
/ 13 июля 2013

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

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

Существует нечто, называемое идентифицирующими и неидентифицирующими отношениями. При идентификации отношений FK является частью PK в таблице «многие ко многим». Например, скажем, у нас есть таблицы Person, Company и таблица «многие ко многим» Employment. В идентифицирующих отношениях fk PersonID и CompanyID являются частью pk, поэтому мы не можем повторить комбинацию PersonID, CompanyID.

TABLE Employment(PersonID int (PK,FK), CompanyID int (PK,FK))

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

TABLE Employment(EmploymentID int (PK), PersonID int (FK), CompanyID int (FK), 
                     FromDate datetime, ToDate datetime)
0 голосов
/ 04 декабря 2009

Правильный ответ:

  • Первичный ключ ('table1fk' , 'table2fk')
  • Еще один индекс по ('table2fk' , 'table1fk')

Потому что:

  • Вам не нужен индекс только для table1fk или table2fk: оптимизатор будет использовать PK
  • Скорее всего, вы будете использовать таблицу «обоими» способами
  • Добавление суррогатного ключа необходимо только из-за мозговых ORM
0 голосов
/ 04 декабря 2009

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

ADD KEY ('table2fk', 'table1fk')
0 голосов
/ 04 декабря 2009

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

...