Необходимость использования внешнего ключа в данном случае (InnoDB/ mysql)
-
05-07-2019 - |
Вопрос
недавно я перенес всю свою базу данных из 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, если дано, используется как описано ранее.