Необходимость внешнего ключа в этом случае (innoDB / mysql) - PullRequest
1 голос
/ 27 ноября 2009

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

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

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

id (pr_key)
name

сообщения

id (pr_key)
user_id
message

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

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

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

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

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

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

Спасибо!

Ответы [ 2 ]

3 голосов
/ 27 ноября 2009

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

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

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

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

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

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

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

@ Ноа, зацените Другой ТАК вопрос

2 голосов
/ 27 ноября 2009

Независимо от того, устанавливаете ли вы формальное правило 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.

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

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

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

...