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

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

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

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

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

24 ответов


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

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


Я также отмечу, что электронная почта-плохой выбор для создания уникального поля, есть люди и даже малые предприятия, которые имеют общий адрес электронной почты. И как номера телефонов,электронные письма могут быть повторно использованы. Jsmith@somecompany.com может легко принадлежать Джону Смиту один год и Джулии Смит два года спустя.

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


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

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


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

  1. медленнее при выполнении соединений.

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

  3. адрес электронной почты может измениться, что заставляет все записи использовать это как внешний ключ для обновления. Поскольку адрес электронной почты не меняется так часто, проблема производительности, вероятно, незначительна. Большая проблема заключается в том, что вы должны убедиться, чтобы обеспечить его. Если вам нужно написать код, это больше работы и вводит возможность ошибок. Если ваш компонент database engine поддерживает "ON update cascade", это незначительная проблема.

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

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

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

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

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


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

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


Я не знаю, Может ли это быть проблемой в вашей настройке, но в зависимости от ваших СУБД значения столбцов могут быть регистр. Документы PostgreSQL говорят:"если вы объявляете столбец уникальным или первичным ключом, неявно сгенерированный индекс чувствителен к регистру". Другими словами, если вы принимаете пользовательский ввод для поиска в таблице с электронной почтой в качестве первичного ключа, и пользователь предоставляет "John@Doe.com-ты не найдешь ...john@doe.com".


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


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

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

systempuntoout спросил,

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

Что это каскадные для.

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

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


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

такой:

CREATE TABLE myTable(
    id integer primary key,
    email text UNIQUE
);

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


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


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

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

чтение здесь и здесь.


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

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

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

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


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


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


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

как отметил @HLGEM "Jsmith@somecompany.com может легко принадлежать Джону Смиту один год и Джулии Смит два года спустя."в этом случае, если Джон Смит захочет воспользоваться вашими услугами, вы должны либо отказаться использовать его адрес электронной почты, либо удалить все записи, относящиеся к Джулии Смит.

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

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


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


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


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


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


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


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


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


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