使用电子邮件地址作为主键?

rob*_*ert 225 sql database postgresql database-design

与自动递增数字相比,电子邮件地址是主要的不良候选人吗?

我们的Web应用程序需要电子邮件地址在系统中是唯一的.所以,我想过用电子邮件地址作为主键.但是我的同事建议字符串比较比整数比较慢.

是不是使用电子邮件作为主键的正当理由?

我们正在使用PostgreSQL.

Sjo*_*erd 278

字符串比较比int比较慢.但是,如果您只是使用电子邮件地址从数据库中检索用户,则无关紧要.如果您有多个连接的复杂查询,这很重要.

如果将有关用户的信息存储在多个表中,则users表的外键将是电子邮件地址.这意味着您多次存储电子邮件地址.

  • +1提及外键; 这是主要问题 (110认同)
  • @Sjoerd:问题不在于电子邮件地址被多次存储,虽然这绝对是低效率的,但是今天谁关心硬盘空间.大多数企业没有谷歌规模,这很重要.问题是之后无法更改电子邮件地址,因为它既是主键又引用为外键. (11认同)

HLG*_*GEM 175

我还要指出,电子邮件是创建一个独特领域的不好选择,有人甚至小企业共享一个电子邮件地址.和电话号码一样,电子邮件可以重复使用.Jsmith@somecompany.com可以很容易地属于约翰史密斯一年,而朱莉亚史密斯可以两年后.

电子邮件的另一个问题是它们经常变化.如果你加入其他表作为密钥,那么你将不得不更新其他表,当整个客户公司更改他们的电子邮件时,这可能会受到很大影响(我已经看到了).

  • +1提及级联更新问题.这就是为什么朋友们让朋友只使用代理键;-). (45认同)
  • @HLGEM:我不想进入无休止的争论,但你不能说在不知道背景的情况下,基于假设的提议密钥不是唯一的.例如,从电话公司的角度来看,电话号码根据定义唯一地标识客户.是的,你可以说,"但如果你打电话给那个号码有两三个人可能会回答怎么办?" 但这无关紧要.从电话公司的角度来看,根据定义,这是一个客户.(继续 ...) (15认同)
  • (续)同样,如果您正在构建一个主要关注电子邮件通信的系统 - 可能是消息调度系统或通知转发系统 - 那么根据定义,可能是电子邮件地址唯一地标识用户.如果多人共享该电子邮件地址,则无关紧要.它们是单个消息目标,因此,它们是单个用户."用户"和"客户"不必是"个人"的同义词. (14认同)
  • @onedaywhen和@jay,只是因为你认为它应该是独一无二的并不能让它独一无二.是的,丈夫和妻子可能是不同的客户.只是因为你没有遇到过这个并不意味着它不会发生.我遇到过这种情况,确实发生了这种情况,这就是为什么不管你认为应该是否应该发送电子邮件,都不应该被认为是唯一的.这是你要求退缩的要求,因为它本身就是错误的. (12认同)
  • 啊,我根本不喜欢这句话......代理钥匙也可能是问题的根源; 是的,应用程序对于更改业务和/或完整性规则将更加健壮,但是信息可能会更容易丢失,并且记录的标识变得不那么清晰.所以我不会在这里推荐一个拇指规则...... (10认同)
  • 由于代理键,我从未在30年的数据库工作中丢失记录. (4认同)
  • ......虽然我不确定我是否愿意:我认为他们就像我一样,认为电子邮件地址是可验证的(他们要求我回复他们发送的电子邮件)并且用户熟悉(即我可以记住我自己的电子邮件地址!),这两者都是好钥匙的属性. (4认同)
  • @sleke我喜欢这句话:"这就是朋友们让朋友们只使用代理键的原因 (3认同)
  • 更有可能的是,电子邮件地址将用作登录ID.这可能会给1%的客户带来不便,但相对于必须选择并记住唯一的用户名,其他99%的用户会有更愉快的体验.唯一的另一种选择是OpenID,大多数人都没有. (3认同)
  • 我经常要求的许多网站都提供一个唯一的电子邮件地址来识别我:亚马逊,谷歌,微软等.请告诉我如何"回击"这个要求给他们. (3认同)
  • 还要添加...人们在线创建帐户时男性TYPO错误...这也将使您在整个地方更改电子邮件地址变得噩梦. (3认同)

Ste*_*owe 97

主键应该是唯一不变的

电子邮件地址会像季节一样变化 可用作查找的辅助键,但主键的选择较差.

  • 良好密钥的属性应该是稳定的,但不一定是不可变的. (17认同)
  • 如果您有选择,请选择常量/不可变键; 你在路上的工作少了; 仅仅因为SQL支持级联更新并不意味着它总是一个好主意! (17认同)
  • @Vincent Malgrat:"级联更新......刹车db规范化" - 你认为你误解了规范化的概念! (7认同)
  • @onedaywhen:是的!否则,为什么SQL支持级联更新? (5认同)
  • @Vincent Malgrat:感谢您确认您确实误解了规范化的概念."你不应该在多行上重复相同的信息" - 你真的想说"信息"吗?!复合键通常涉及在多行上重复的值.对于外键,引用值而不是"重复",差别很大.如果具有三个或更多行,则具有两个值(例如,"是"和"否")的单列域将在引用表中的多行上具有相同的值.这是非常基本的东西! (5认同)

Jay*_*Jay 63

使用电子邮件地址作为主键的缺点:

  1. 在进行连接时更慢.

  2. 具有已发布外键的任何其他记录现在具有更大的值,占用更多磁盘空间.(考虑到今天的磁盘空间成本,这可能是一个微不足道的问题,除非记录现在需要更长的时间来阅读.请参阅#1.)

  3. 电子邮件地址可能会更改,这会强制更新使用此作为外键的所有记录.由于电子邮件地址不会经常发生变化,因此性能问题可能很小.更大的问题是你必须确保提供它.如果你必须编写代码,这是更多的工作,并引入了错误的可能性.如果您的数据库引擎支持"on update cascade",那么这是一个小问题.

使用电子邮件地址作为主键的优点:

  1. 您可以完全消除一些连接.如果您需要的"主记录"是电子邮件地址,那么使用抽象整数键,您必须进行连接才能检索它.如果密钥是电子邮件地址,那么您已经拥有它并且不需要加入.这对你有什么帮助取决于这种情况出现的频率.

  2. 当您进行即席查询时,人们很容易看到正在引用的主记录.在尝试跟踪数据问题时,这可能是一个很大的帮助.

  3. 你几乎肯定会需要电子邮件地址的索引,所以将它作为主键消除了一个索引,从而提高了插入的性能,因为它们现在只有一个索引要更新而不是两个.

在我的拙见中,无论如何,这都不是一个扣篮.我倾向于在实用的时候使用自然键,因为它们更容易使用,并且在大多数情况下缺点往往并不重要.

  • @Matthew恕我直言,它仍然是一个PITA.例如,假设当你设计你的国家表时,只有两个表引用它,没有biggy,但随着时间的推移,它变成了20个表,每个表有数十万条记录.有些参考没有.这使得单个逻辑写入最终成为数万个写入,并且它不会使其成为所有表,因为有人在添加表时忘记了引用.这是我在2个国家代码表上发生的确切事情. (5认同)
  • @Ash:你是"优化"和"过早优化"之间的区别.但是好的,通过相同的推理,我见过的所有缺点都是过早的优化.那么你离开了哪里?对于#2,我发现在尝试进行即席查询时要输入额外的连接是一个很大的痛苦.记录通常有多个外键,因此您可能需要多个连接才能获得可理解的数据.如果通过"体面的查询工具",你的意思是指出一个你想要看到的数据,而不是你告诉它,并且神奇地为你做了连接,我想看看它是如何工作的. (4认同)
  • 优势1和3是过早的优化,优势2是次要的优势,任何体面的查询工具都可以完全克服。 (2认同)

mer*_*ike 12

这很糟糕.假设某些电子邮件提供商破产.然后,用户将要更改他们的电子邮件.如果您使用电子邮件作为主键,则用户的所有外键都将复制该电子邮件,因此很难更改...

......我甚至还没有开始谈论性能方面的考虑.

  • 为"假设某个电子邮件提供商破产"这一行的+1. (5认同)
  • 根据定义,外键引用包含它所引用的行的主键的值。换句话说,它复制了主键的值。(因此,复制不是由更改值引起的。但是由于此复制以及强制执行该复制的约束,因此更改更加困难)。 (2认同)

xlt*_*ttj 12

我不知道这可能是您的设置中的问题,但根据您的RDBMS,列的值可能区分大小写.PostgreSQL的文件说:"如果你声明一个列UNIQUE或PRIMARY KEY,隐式生成指数是区分大小写的." 换句话说,如果你接受用户输入的表格与电子邮件作为主键搜索,用户提供了"John@Doe.com",你不会找到"john@doe.com".

  • 在这方面值得一提的是,John @ Doe.com和john@Doe.com可能是同一个邮箱,也可能是不同的邮箱而你无法说出 - 规范中没有任何内容可以说明本地部分是否属于案例 - 敏感. (7认同)

Sim*_*olt 11

似乎没有人提到电子邮件地址可能被视为私有的可能问题.如果电子邮件地址是主键,则配置文件页面URL很可能看起来像..../Users/my@email.com.如果您不想公开用户的电子邮件地址怎么办?您必须找到一些其他识别用户的方法,可能通过一个唯一的整数值来制作URL ..../Users/1.然后你最终得到一个唯一的整数值.


Raf*_*afa 9

逻辑层面,电子邮件是自然密钥.在物理层面,假设您使用的是关系数据库,则自然键不适合作为主键.原因主要是其他人提到的性能问题.

因此,可以调整设计.自然键成为备用键(UNIQUE,NOT NULL),并使用代理/人工/技术键作为主键,在您的情况下可以是自动增量.

systempuntoout问道,

如果有人想要更改他的电子邮件地址怎么办?你打算改变所有的外键吗?

这就是级联的目的.

使用数字代理键作为主键的另一个原因与索引在您的平台中的工作方式有关.例如,在MySQL的InnoDB中,表中的所有索引都预先设置了主键,因此您希望PK尽可能小(对于速度和大小的清醒).与此相关的是,当主键按顺序存储时,InnoDB更快,并且字符串对此没有帮助.

使用字符串作为备用键时要考虑的另一件事是,使用您想要的实际字符串的哈希可能会更快,跳过某些字母的大写和小写的情况.(我实际上在这里找到了一个参考,以确认我刚才所说的内容;仍在寻找...)


Bry*_*end 6

是的,这是一个糟糕的主键,因为您的用户会想要更新他们的电子邮件地址。


ibr*_*ram 5

是的,最好使用整数。您还可以将电子邮件列设置为唯一约束。

像这样:

CREATE TABLE myTable(
    id integer primary key,
    email text UNIQUE
);
Run Code Online (Sandbox Code Playgroud)

  • 你能详细说明一下吗? (21认同)
  • 为什么它“更好”?有什么原因或来源吗? (9认同)