Структура отношений «многие ко многим» в SQL Server с дополнительным столбцом первичного ключа или без него? - PullRequest
2 голосов
/ 08 октября 2009

Предположим, что у нас есть две таблицы: Роли и Отчеты . И существует отношения многие ко многим между ними. Конечно, единственное решение Мне приходит в голову создать кросс-таблицу, назовем ее RoleReport . Я вижу два подхода к структуре этой таблицы:

1. Columns: RoleReportId, RoleId, ReportId
   PK: RoleReportId
2. Columns: RoleId, ReportId
   PK: RoleId, ReportId

Есть ли реальная разница между ними (производительность или что-то еще)?

Ответы [ 7 ]

10 голосов
/ 08 октября 2009

Вам все равно понадобится составной UNIQUE индекс (RoleId, ReportId).

Нет смысла не делать это PRIMARY KEY.

Если вы сделаете это CLUSTERED PRIMARY KEY (по умолчанию), это будет лучше с точки зрения производительности, поскольку будет меньше по размеру.

Кластерный первичный ключ будет содержать только два столбца в каждой записи: RoleID и ReportID, а вторичный индекс будет содержать три столбца: RoleID, ReportID и RoleReportID (в качестве указателя строки) .

Возможно, вы захотите создать дополнительный индекс для ReportID, который можно использовать для поиска всех Roles по заданному Report.

Был бы некоторый смысл в создании суррогатного ключа для этих отношений, если выполняются два следующих условия:

  1. У вас есть дополнительные атрибуты в ваших отношениях (т. Е. Эта таблица содержит дополнительные столбцы, такие как Date или что-то еще)
    • У вас есть лотов таблиц, которые ссылаются на это отношение с FOREIGN KEY

В этом случае было бы лучше иметь один столбец PRIMARY KEY для ссылки в FOREIGN KEY отношениях.

Так как у вас, кажется, нет такой необходимости, просто сделайте композит PRIMARY KEY.

5 голосов
/ 08 октября 2009

На самом деле не нужно RoleReportId. Это ничего не добавляет к отношениям.

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

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

2 голосов
/ 08 октября 2009

Семантически, разница в том, что вы используете в качестве первичного ключа.

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

Это, конечно, субъективно. Я не утверждаю, что это Единый Истинный Путь (тм).

2 голосов
/ 08 октября 2009

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

1 голос
/ 08 октября 2009

Если у вас много строк, то может быть полезно иметь надлежащим образом упорядоченные индексы для столбцов RoleId и / или ReportId, поскольку это ускорит операции поиска, но, наоборот, замедлит операции вставки / удаления. Это классическая проблема с профилем использования ...

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

Но в целом, мы говорим здесь о миллисекундах. Это становится актуальным, только если имеется огромное количество данных (скажем, более 10.000 строк) ...

0 голосов
/ 08 октября 2009

Преимущество использования RoleReportID в качестве первичного ключа, состоящего из одного столбца, возникает тогда, когда вам (или другому парню, в зависимости от структуры вашей компании) необходимо написать интерфейс, который рассматривает индивидуальные роли <-> отношения отчета (например , чтобы удалить один). В этот момент вы можете предпочесть тот факт, что вам нужно обратиться только к одному столбцу, а не к двум, чтобы идентифицировать запись связывания.

Кроме этого, вам не нужен столбец RoleReportID.

0 голосов
/ 08 октября 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...