Почему нехорошо иметь первичный ключ в соединительной таблице? - PullRequest
21 голосов
/ 19 мая 2009

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

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

Почему не хорошо иметь первичный ключ в этом примере?

create_table :categories_posts, :id => false do |t|
  t.column :category_id, :integer, :null => false
  t.column :post_id, :integer, :null => false
end
add_index :categories_posts, :category_id
add_index :categories_posts, :post_id

РЕДАКТИРОВАТЬ: Как я уже упоминал в Cletus, я могу понять потенциальную полезность поля автоматического номера в качестве первичного ключа даже для таблицы соединений. Однако в приведенном выше примере автор явно избегает создания поля автоматического нумерации с синтаксисом «: id => false» в операторе «create table». Обычно Rails автоматически добавляет поле идентификатора автоматического номера в таблицу, созданную при такой миграции, и это становится первичным ключом. Но для этой таблицы соединений, автор специально это предотвратил. Я не был уверен, почему он решил следовать этому подходу.

Ответы [ 8 ]

46 голосов
/ 19 мая 2009

Некоторые заметки:

  1. Сочетание category_id и post_id само по себе уникально, поэтому дополнительный столбец ID является излишним и бесполезным
  2. Фраза "нехорошо иметь первичный ключ" неверна в скринкасте. У вас все еще есть первичный ключ - он просто состоит из двух столбцов (например, CREATE TABLE foo (cid, pid, PRIMARY KEY (cid, pid)). Для людей, которые привыкли присваивать значения ID везде, где это может показаться Странно, но в реляционной теории это вполне правильно и естественно: автор скриншота лучше сказал бы, что «нехорошо иметь неявный целочисленный атрибут с именем« ID »в качестве первичного ключа».
  3. Излишне иметь дополнительный столбец, потому что вы все равно поместите уникальный индекс в комбинацию category_id и post_id, чтобы избежать вставки повторяющихся строк
  4. Наконец, хотя общепринятая номенклатура заключается в том, чтобы называть ее «составным ключом», это также избыточно. Термин «ключ» в теории отношений на самом деле представляет собой набор из нуля или более атрибутов, которые однозначно идентифицируют строку, поэтому можно сказать, что первичным ключом является category_id, post_id
  5. Поместите столбец НАИБОЛЕЕ ВЫБЕРИТЕ ПЕРВЫЙ в объявлении первичного ключа. Обсуждение построения деревьев b (+ / *) выходит за рамки этого ответа (некоторые обсуждения более низкого уровня см .: http://www.akadia.com/services/ora_index_selectivity.html), но в вашем случае вы, вероятно, захотите его на post_id , category_id, поскольку post_id будет показываться реже в таблице и, следовательно, сделает индекс более полезным. Конечно, поскольку таблица очень мала и индекс будет, по сути, строками данных, это не очень важно. Это было бы в более широких случаях, когда таблица шире.
3 голосов
/ 19 мая 2009

Это плохая идея - не иметь первичный ключ в какой-либо таблице, точка (если СУБД является реляционной СУБД или СУБД SQL). Первичные ключи являются важной частью целостности вашей базы данных.

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

3 голосов
/ 19 мая 2009

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

Но это просто говорит, почему это не Хорошая Идея ... но почему это было бы Плохой Идеей?

Рассмотрим накладные расходы, которые добавит столбец идентификаторов. Таблица будет занимать на 50% больше дискового пространства. Хуже ситуация с индексом. В поле идентификатора вы должны вести счетчик идентификаторов плюс второй индекс. Вы будете утроить дисковое пространство и утроить работу, которую необходимо выполнить для каждой вставки. Единственным преимуществом является несколько более короткое предложение WHERE в команде DELETE.

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

3 голосов
/ 19 мая 2009

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

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

3 голосов
/ 19 мая 2009

Администратор БД сказал бы, что первичный ключ в этом случае на самом деле является комбинацией двух столбцов FK. Так как Rails / ActiveRecord не подходит для составных ПК (по крайней мере, по умолчанию), это может быть причиной.

2 голосов
/ 19 мая 2009

Я хотел бы прокомментировать следующий комментарий: «Неправильно говорить ноль или более».

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

Я также хотел бы прокомментировать, что не правильно говорить, что это неправильно, сказать «ноль или больше». Теория отношений, общеизвестная сегодня среди немногих людей, которые все еще пытаются изучить детали этой теории, на самом деле ТРЕБУЕТ возможности ключа без атрибутов.

Но когда я нажал кнопку «комментарий», система ответила мне, что для комментирования требуется оценка репутации 50 (или около того).

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

2 голосов
/ 19 мая 2009

Размещение наиболее селективного столбца первым должно иметь значение только в декларации INDEX. В объявлении KEY это не должно иметь значения (потому что, как было правильно указано, KEY - это SET, а внутри набора порядок не имеет значения - набор {a1, a2} такой же, как {a2). а1}).

Если продукт СУБД таков, что порядок атрибутов внутри объявления KEY имеет значение, то продукт СУБД виноват в неправильном различении логического дизайна базы данных (той части, где вы делаете объявление KEY) и физический дизайн базы данных (часть, где вы делаете декларацию INDEX).

1 голос
/ 19 мая 2009

Плюсы наличия одного ПК

  • Уникально идентифицирует строку с одним значением
  • Позволяет легко ссылаться на отношение из других источников, если это необходимо
  • Некоторые инструменты хотят, чтобы у вас было одно целое значение pk

Минусы наличия одного ПК

  • использует больше дискового пространства
  • Нужно 3 индекса, а не 1
  • Без уникального ограничения вы можете получить несколько строк для одного и того же отношения

Примечания

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