Является ли string или int предпочтительным для внешних ключей? - PullRequest
10 голосов
/ 27 января 2011

У меня есть пользовательская таблица со столбцами userid и username, и оба они уникальны.

Между userid и username, которые лучше использовать в качестве внешнего ключа, и почему?Мой босс хочет использовать строку, это нормально?

Ответы [ 4 ]

25 голосов
/ 27 января 2011

Похоже, у вас есть как суррогатный ключ (int userId), так и натуральный ключ (char или varchar username). Любой столбец можно использовать в качестве первичного ключа для таблицы, и в любом случае вы все равно сможете обеспечить уникальность другого ключа.

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

Вот некоторые соображения при выборе того или иного пути:

Случай использования суррогатных ключей (например, UserId INT AUTO_INCREMENT)

Если вы используете суррогат (например, UserId INT AUTO_INCREMENT) в качестве первичного ключа, то все таблицы, ссылающиеся на таблицу MyUsers, должны затем использовать UserId в качестве внешнего ключа.

Тем не менее, вы все равно можете применить уникальность столбца username, используя дополнительный уникальный индекс , например ::

CREATE TABLE `MyUsers` (
  `userId` int NOT NULL AUTO_INCREMENT,
  `username` varchar(100) NOT NULL,
  ... other columns
  PRIMARY KEY(`userId`),
  UNIQUE KEY UQ_UserName (`username`)

Согласно @Dagon, использование узкого первичного ключа (например, int) имеет преимущества в производительности и хранении по сравнению с использованием более широкого (и переменной длины) значения, такого как varchar. Это преимущество также влияет на другие таблицы, которые ссылаются на MyUsers, так как внешний ключ к userid будет сужаться.

Еще одним преимуществом суррогатного целочисленного ключа является то, что имя пользователя можно легко изменить, не затрагивая таблицы, ссылающиеся на MyUsers. Если username использовался в качестве естественного ключа, то таблицы были связаны с MyUsers через username, что делает более неудобным изменение имени пользователя (поскольку в противном случае отношение внешнего ключа было бы нарушено). Если требуется обновить имена пользователей для таблиц, использующих username в качестве внешнего ключа, для сохранения целостности данных необходимо использовать метод, такой как ON UPDATE CASCADE .

Кейс для использования Natural Keys (т.е. имя пользователя)

С другой стороны, для использования суррогатных ключей для других таблиц, которые ссылаются на MyUsers через суррогатный ключ, всегда требуется join назад к таблице MyUsers для получения имени пользователя. Одним из потенциальных преимуществ естественных ключей является то, что если для запроса требуется только столбец Username из таблицы, ссылающейся на MyUsers, ему не нужно возвращаться к MyUsers для получения имени пользователя, что сэкономит некоторые накладные расходы.

Дальнейшие ссылки на естественные и суррогатные дебаты и компромиссы здесь и здесь

3 голосов
/ 27 января 2011

Значение int составляет 4 байта, строка может содержать столько байтов, сколько вам нужно.Из-за этого int всегда будет работать лучше.Если, конечно, вы придерживаетесь имен пользователей длиной менее 4 символов:)

Кроме того, вы никогда не должны использовать столбец в качестве PK / FK, если данные внутри самого столбца могут измениться.Пользователи, как правило, меняют свои имена пользователей, и даже если эта функция не существует в вашем приложении прямо сейчас, возможно, это произойдет через несколько лет.Когда наступит этот день, у вас может быть 1000 таблиц, которые ссылаются на эту пользовательскую таблицу, а затем вам придется обновить все 1000 таблиц в транзакции, и это просто плохо.

3 голосов
/ 27 января 2011

int будет индексироваться быстрее, может быть, а может и не быть проблемой, трудно сказать на основании того, что вы предоставили

0 голосов
/ 22 мая 2019

Это зависит от внешнего ключа: если ваша компания контролирует его, то я рекомендую использовать Int, если для него есть поле ID.Однако иногда поле идентификатора отсутствует в таблице, поскольку другой ключ имеет смысл в качестве альтернативного уникального ключа.Таким образом, поле ID может быть суррогатным ключом в этом случае.

Практическое правило. Тип данных внешнего ключа должен соответствовать типу данных первичного ключа.

Вот исключение: как насчет внешних ключей, которые не принадлежат вашей компании?Как насчет внешних ключей к базам данных и API, которые вы не можете контролировать?Эти идентификаторы всегда должны быть строками IMO.

Чтобы убедить вас, я задаю следующие вопросы:

Вы занимаетесь математикой?Вы увеличиваете это?У вас есть контроль над этим?API печально известны изменениями, даже типы данных МОГУТ быть изменены в чужой базе данных ... так сколько это будет мешать вам, когда int ID станет шестнадцатеричным?

...