Использовать адрес электронной почты в качестве первичного ключа?

225

Является ли адрес электронной почты плохим кандидатом для первичного по сравнению с автоматически увеличивающимися номерами?

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

Является ли веской причина не использовать электронную почту в качестве первичного ключа?

Мы используем PostgreSQL.

  • 5
    Что вы подразумеваете под «первичным»? Если адрес электронной почты должен быть уникальным, он является ключевым и требует уникальных ограничений. Если вы решите «продвигать» его как «первичное», это произвольно, если только для этого нет практической причины, например, оптимизации плохо работающей системы.
  • 7
    Если вы хотите, чтобы в вашей базе данных использовался уникальный адрес электронной почты, создайте столбец с уникальным индексом, но не используйте его в качестве первичного ключа.
Показать ещё 12 комментариев
Теги:
database
database-design

25 ответов

269
Лучший ответ

Сравнение строк медленнее, чем сравнение int. Тем не менее, это не имеет значения, если вы просто извлекаете пользователя из базы данных, используя адрес электронной почты. Это имеет значение, если у вас есть сложные запросы с несколькими объединениями.

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

  • 106
    +1 за упоминание внешних ключей; это главная проблема
  • 9
    @Sjoerd: Проблема не в том, что адрес электронной почты хранится несколько раз, хотя это определенно неэффективно, а в том, кому сегодня нужно место на жестком диске. У большинства компаний нет Google-масштаба, где это будет иметь значение. Проблема в том, что адрес электронной почты не может быть изменен впоследствии, потому что это и первичный ключ, и ссылка на него как на внешний ключ.
Показать ещё 2 комментария
169

Я также укажу, что письмо является плохим выбором для создания уникальной области, есть люди и даже малые предприятия, которые делят адрес электронной почты. И как номера телефонов, электронные письма могут быть повторно использованы. [email protected] может легко принадлежать Джону Смиту один год, а Джулия Смит - через два года.

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

  • 45
    +1 за упоминание о проблеме каскадного обновления. Вот почему друзья позволяют друзьям использовать только суррогатные ключи ;-).
  • 3
    @sleke Мне нравится фраза: «Вот почему друзья позволяют друзьям использовать только суррогатные ключи
Показать ещё 11 комментариев
91

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

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

  • 17
    Свойство хорошего ключа заключается в том, что оно должно быть стабильным, но НЕ обязательно неизменным.
  • 5
    @onedaywhen: Да! Иначе, почему SQL поддерживает каскадные обновления?
Показать ещё 7 комментариев
58

Недостатки использования адреса электронной почты в качестве первичного ключа:

  • Медленнее при объединении.

  • Любая другая запись с открытым внешним ключом теперь имеет большее значение, занимая больше места на диске. (Учитывая стоимость дискового пространства сегодня, это, вероятно, тривиальная проблема, за исключением того, что запись теперь занимает больше времени. См. № 1.)

  • Можно изменить адрес электронной почты, который заставляет все записи использовать это как внешний ключ для обновления. Поскольку адрес электронной почты не меняет все часто, проблема с производительностью, вероятно, незначительна. Большая проблема заключается в том, что вы должны быть уверены в ее обеспечении. Если вам нужно написать код, это больше работы и вводит возможность ошибок. Если ваш механизм базы данных поддерживает "на каскаде обновления", это незначительная проблема.

Преимущества использования адреса электронной почты в качестве первичного ключа:

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

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

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

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

  • 1
    +1 за замечание, что изменяемые ссылочные ключи являются PITA
  • 0
    @ Конрад: Хотя, он действительно указывает, что это не PITA, если у вас есть движок, который поддерживает ОБНОВЛЕНИЕ КАСКАДА. Это не проблема в этой точке кода; единственная реальная проблема заключается в том, насколько обширно обновление и насколько широка ключ. Адрес электронной почты может быть немного большим, но ОБНОВЛЕНИЕ CASCADE для PK с 2-символьным кодом страны не имеет большого значения.
Показать ещё 4 комментария
11

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

... и я даже не заговорил о соображениях производительности.

  • 0
    Как изменение адресов электронной почты может привести к дублированию? Если пользователь А не изменит свой адрес электронной почты, а затем пользователь Б не изменит свой адрес электронной почты так, чтобы он совпадал со старым значением пользователя А, и ваши обновления выполняются не по порядку. Я думаю, что это возможно удаленно.
  • 2
    Ссылка на внешний ключ по определению содержит значение первичного ключа строки, на которую она ссылается. Иными словами, он дублирует значение первичного ключа. (Таким образом, дублирование не вызвано изменением значения. Но изменение сложнее из-за этого дублирования и ограничения, обеспечивающего его).
Показать ещё 7 комментариев
10

Никто, кажется, не упомянул о возможной проблеме того, что адреса электронной почты можно считать конфиденциальными. Если адрес электронной почты является основным ключом, URL-адрес страницы профиля, скорее всего, будет выглядеть примерно как ..../Users/[email protected]. Что делать, если вы не хотите раскрывать адрес электронной почты пользователя? Вам нужно будет найти другой способ идентификации пользователя, возможно, с помощью уникального целочисленного значения, чтобы сделать URL-адреса типа ..../Users/1. Тогда вы все равно получите уникальное целочисленное значение.

10

Я не знаю, может ли это быть проблемой в вашей настройке, но в зависимости от вашей РСУБД значения столбцов могут быть чувствительны к регистру. В документах PostgreSQL говорится: "Если вы объявляете столбец как UNIQUE или PRIMARY KEY, неявно сгенерированный индекс учитывает регистр". Другими словами, если вы принимаете пользовательский ввод для поиска в таблице с адресом электронной почты в качестве первичного ключа, а пользователь предоставляет "[email protected]", вы не найдете "[email protected]".

  • 7
    В этой связи стоит упомянуть, что [email protected] и [email protected] могут быть одним и тем же почтовым ящиком или разными почтовыми ящиками, и вы не можете сказать - в спецификации нет ничего, чтобы сказать, является ли локальная часть регистром чувствительны.
  • 0
    Вы правы, это зависит от почтового сервера.
Показать ещё 1 комментарий
8

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

По этой причине дизайн может быть адаптирован. Естественным ключом становится альтернативный ключ (UNIQUE, NOT NULL), и вы используете суррогатный/искусственный/технический ключ в качестве первичного ключа, который может быть автоматическим приращением в вашем случае.

systempuntoout спросил,

Что делать, если кто-то хочет изменить свой адрес электронной почты? Вы тоже будете менять все внешние ключи?

Что для каскадирование для.

Другая причина использования числового суррогатного ключа в качестве первичного ключа связана с тем, как индексирование работает на вашей платформе. В MySQL InnoDB, например, все индексы в таблице имеют первичный ключ, предварительно привязанный к ним, поэтому вы хотите, чтобы PK был как можно меньше (для скорости и размера). Также, связанный с этим, InnoDB работает быстрее, когда первичный ключ хранится в последовательности, а строка там не поможет.

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

4

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

  • 0
    Думаю, я бы сказал, что теперь у нас есть каскад, это не проблема
4

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

вот так:

CREATE TABLE myTable(
    id integer primary key,
    email text UNIQUE
);
  • 8
    Почему это "лучше"? Какие-либо причины или источники?
  • 3
    опыт и смысл :)
Показать ещё 1 комментарий
3

Я не слишком хорошо знаком с postgres. Первичные ключи - большая тема. Я видел несколько отличных вопросов и ответов на этом сайте (stackoverflow.com).

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

некоторое чтение здесь и здесь.

3

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

2

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

Как отметил @HLGEM, "[email protected] может легко принадлежать Джону Смиту один год, а Джулия Смит - через два года". в этом случае, если Джон Смит захочет получить ваше обслуживание, вам либо придется отказаться от использования своего адреса электронной почты, либо удалить все ваши записи, относящиеся к Джулии Смит.

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

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

2

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

2

Используйте GUID в качестве первичного ключа... таким образом вы можете сгенерировать его из своей программы, когда вы выполняете INSERT, и вам не нужно получать ответ от сервера, чтобы узнать, что такое первичный ключ. Он также будет уникальным для таблиц и баз данных, и вам не нужно беспокоиться о том, что произойдет, если вы однажды усечете таблицу, а автоинкремент получит reset до 1.

  • 2
    Если вы не заботитесь о производительности, используйте GUID. Нет-нет № 1, если вы строите систему, которая должна будет масштабироваться
  • 0
    нет ... см. davybrion.com/blog/2009/05/…
Показать ещё 1 комментарий
2

Ваш коллега прав: используйте ключевое слово autoincrementing для вашего первичного ключа.

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

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

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

  • 1
    «Всегда внимательно относитесь к выполнению требования x только потому, что вашему приложению требуется требование x». - худший совет, который я прочитал за последнее время.
  • 0
    Меня не убеждает ваш «аргумент» - в реальной жизни часто бывают ситуации, когда некоторые важные данные (например, номер телефона) не будут доступны сразу. Если такое поле помечено как NOT NULL в базе данных, пользователям потребуется загрязнять данные фиктивными полями (например, 123), а не оставлять их пустыми. Было бы более практично позволить приложению обрабатывать ограничения (и в этом случае приложение может пометить пустое поле как элемент действия).
Показать ещё 3 комментария
1

Первичный ключ должен быть выбран статическим атрибутом. Поскольку адреса электронной почты не являются статичными и могут использоваться несколькими кандидатами, поэтому использовать их в качестве первичного ключа не рекомендуется. Кроме того, адреса электронной почты представляют собой строки, обычно имеющие определенную длину, которая может быть больше, чем уникальный идентификатор, который мы хотели бы использовать [len (email_address) > len (unique_id)], поэтому для этого потребовалось бы больше места и даже худшее, что они хранятся несколько раз, как внешний ключ, И, следовательно, это приведет к ухудшению производительности.

1

Если у вас есть значение non int в качестве первичного ключа, тогда вложения и поиск будут очень медленными при больших данных.

  • 1
    Нет, вставляет это будет медленнее , потому что вам нужны два уникальных индекса: один для сгенерированного первичного ключа и другой для адреса электронной почты.
1

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

1

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

0

Возможно, вам придется рассмотреть любое применимое законодательство о регулировании данных. Электронная почта - это личная информация, и если ваши пользователи, например, являются гражданами ЕС, в рамках GDPR они могут поручить вам удалить их информацию из ваших записей (помните, что это применимо независимо от того, в какой стране вы находитесь).

Если вам необходимо сохранить саму запись в базе данных по ссылочной целостности или историческим причинам, таким как аудит, использование суррогатного ключа позволит вам просто ОБНОВИТЬ все поля персональных данных. Это, очевидно, не так просто, если их личные данные являются первичным ключом

0

не используйте адрес электронной почты в качестве первичного ключа, сохраняйте электронную почту как уникальную, но не используйте ее как первичный ключ, используйте идентификатор пользователя или имя пользователя в качестве первичного ключа

0

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

0

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

0

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню