SQL - первичный ключ таблицы "многие-ко-многим"

Этот вопрос возникает после прочтения комментария в этом вопросе:

Дизайн базы данных

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

В основном это:

PartDevice
----------
PartID (PK/FK)
DeviceID (PK/FK)

против. это:

PartDevice
----------
ID (PK/auto-increment)
PartID (FK)
DeviceID (FK)

Комментарий говорит:

делая два идентификатора, PK означает таблица физически сортируется на диске в этой последовательности. Поэтому, если мы вставим (Part1/Device1), (Part1/Device2), (Part2/Device3), затем (часть 1/Device3) база данных должна будет стол разделить и вставить последний между записями 2 и 3. Для многих записей, это становится очень проблематичным поскольку это включает перетасовку сотен, тысячи или миллионы записей каждый раз добавляется. Напротив, автоинкрементный ПК позволяет записи, которые должны быть прикреплены до конца.

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

Ответ 1

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

Вам не понадобятся индексы для отдельных столбцов, так как таблица должна использоваться только для объединения двух ссылочных таблиц.

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

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

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

Ответ 2

Для таблиц ссылок нет суррогатного ключа.

Только один PK (col1, col2) и еще один уникальный индекс (col2, col1), который вам нужен

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

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

Ответ 3

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

например

PartDevice
----------
ID (PK/auto-increment)
PartID (FK)
DeviceID (FK)
Other Details

Легко вытащить "Другие детали" с помощью PartDevice.ID в качестве FK. Таким образом, необходимо использовать инкрементный первичный ключ.

Ответ 4

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