2010-02-03 4 views
92

Этот вопрос возникает после прочтения комментария в этом вопросе:SQL - многие-ко-многим таблице первичный ключ

Database Design

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

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

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

против этого:

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

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

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

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

+0

отличный вопрос, ожидая ответа от sql guru :) – sbczk

+0

Вот вопрос силимара, размещенный на SO: http://stackoverflow.com/questions/344068/sql-server-clustered-index-order-of-index- вопрос – Tony

+0

(Пробовал добавить это к моему предыдущему комментарию, но не могу) В зависимости от количества вставок вы также можете периодически перестраивать свой индекс, чтобы он быстро возвращал результаты. В SQL Server вы также можете настроить FILLFACTOR индекса, чтобы предоставить достаточно места для вставок, прежде чем он будет перемещать данные. – Tony

ответ

60

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

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

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

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

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

+0

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

+4

@ buffer, я буду придерживаться этого комментария (технически это обобщение, только если я скажу «все таблицы», «подавляющее большинство» основано на опыте).Давайте также подумаем над вашим примером: заказ создается один раз (иногда его можно обновлять, но вряд ли он изменит информацию о ключе/индексе, а больше - для того, чтобы набрать такие вещи, как статус заказа. Однако эти обновления и выборки вам нужно будет сделать распечатывать счета-фактуры или генерировать отчеты по управлению, перевешивают исходную вставку. – paxdiablo

+0

Think Amazon - Тысячи заказов, созданных каждый час. – Medorator

12

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

Один ПК на (col1, col2) и другого уникального индекса (col2, col1) все, что вам нужно

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

Edit: я ответил то же самое здесь: SQL: Do you need an auto-incremental primary key for Many-Many tables?

+0

Спасибо за ссылку ... интересно –

+3

Возможно, с индексом dups на col2 может быть ОК, а не с уникальным индексом (col2, col1). Преимущество индекса с двумя столбцами заключается в том, что он позволяет проводить только индексирование только на col2 или на col1 и col2 (хотя другой индекс, в (col1, col2) также обрабатывает «оба» случая). Недостатком является дополнительное хранилище, необходимое для дополнительной колонки. Это обычно не имеет значения, поэтому совет далек от ужаса. Тем не менее, если col1 и col2 большие или очень разных размеров, вы можете сэкономить себе место, не нанося вреда производительности, выбрав второй указатель только на более короткой колонке. –

+0

@gbn: Второй индекс на (col2, col1) не обязательно должен быть уникальным, не так ли? – Medorator

4

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

8

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

, например

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

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

Смежные вопросы