Необходимость использования внешнего ключа в данном случае (InnoDB/ mysql)

StackOverflow https://stackoverflow.com/questions/1809629

Вопрос

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

Допустим, у меня есть две таблицы:пользователи, сообщения.

Пользователи

id (pr_key)
name

Сообщения

id (pr_key)
user_id
message

Оба поля идентификатора увеличиваются автоматически.

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

Если я решу поместить сюда внешний ключ, я предполагаю, что мне нужно сделать pr_key сообщений как id, так и user_id.

Добавление другого prim_key не просто займет больше места, но и приведет к снижению производительности.

Теперь, если в таблице есть два pr_keys, и я запрашиваю только по одному из них, будут ли у меня те же преимущества в производительности?Или мне нужно явно использовать эти два ключа.

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

Спасибо!

Это было полезно?

Решение

Это имеет целостность данных Преимущества.

это остановит ввод кода приложения с идентификатором пользователя 1234 в таблице сообщений, если в таблице пользователей нет пользователя с идентификатором = 1234.И это остановит приложение от удаления пользователя, когда у пользователя появятся какие-либо сообщения в таблице сообщений.

Имя PK не обязательно должно совпадать с именем FK в ссылающейся дочерней таблице.

"Если я решу поместить сюда внешний ключ, я предполагаю, что мне нужно сделать pr_key сообщений как id, так и user_id."

НЕТ.Вы не меняете ключ в таблице messages, вы просто устанавливаете ограничение внешнего ключа (FK) для столбца User_Id в таблице messages, которое ссылается (указывает) на столбец id в таблице users.В сообщениях не требуется дополнительного PK, и поскольку PK уже уникален (у вас не может быть двух сообщений с одинаковым MessageId), создание PK как для id, так и для user_id не может добавить больше уникальности.)

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

  • PK - это ограничение уникальности строки, для него требуется индекс.
  • FK - это ограничение на значение столбца (оно требует, чтобы значение существовало как значение PK в какой-либо другой таблице, на которую ссылается ссылка) Оно выполняет нет требуется индекс.

@Ной, посмотри на это Другой ТАКОЙ вопрос

Другие советы

Независимо от того, устанавливаете ли вы формальное правило FOREIGN KEY для сообщений (user_id) или нет, простой факт заключается в том, что это отношение внешнего ключа.

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

Во-вторых, как уже сказал Чарльз, объявляя FOREIGN KEY в сообщениях (user_id), что ССЫЛКИ на пользователей (id) позволят вам обеспечить целостность ваших данных. Используя ограничение внешнего ключа, вы можете указать, что делать, когда удаляется запись в таблице пользователей с соответствующими записями в таблице сообщений. Вы можете выбрать ON DELETE CASCADE (удалить все дочерние записи для этой пользовательской записи), ON DELETE RESTRICT (не разрешать удаление пользователя, имеющего записи в таблице сообщений), ON DELETE NO ACTION (игнорировать операции удаления) , ON DELETE SET NULL (сохраняет дочерние записи, но устанавливает для поля user_id значение NULL).

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

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

@Charles Bretana - вопрос, на который вы ссылаетесь, относится к Microsoft SQL Server. Вопрос здесь касается MySQL / InnoDB.

Я бы порекомендовал вам взглянуть на документацию по Ограничения внешнего ключа InnoDB .

  

InnoDB требует индексов на иностранных   ключи и ссылочные ключи так, чтобы   проверка внешнего ключа может быть быстрой и не   требуется сканирование таблицы. в   ссылочная таблица, должна быть   индекс, где столбцы внешнего ключа   перечислены как первые столбцы в   тот же порядок. Такой индекс создан   на ссылочной таблице автоматически   если его не существует (Это в   в отличие от некоторых старых версий, в   какие индексы нужно было создать   явно или создание иностранного   ключевые ограничения потерпят неудачу.)   index_name, если дано, используется как   описано ранее.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top