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

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

我们的networking应用程序需要电子邮件地址在系统中是唯一的。 所以,我想使用电子邮件地址作为主键。 但是我的同事build议string比较比整数比较慢。

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

我们正在使用PostgreSQL

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

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

我还会指出,电子邮件是一个不错的select,使一个独特的领域,有人,甚至小企业共享一个电子邮件地址。 像电话号码一样, 电子邮件可以被重复使用。 Jsmith@somecompany.com可以很容易地属于一年的约翰·史密斯和两年后的朱莉娅·史密斯。

电子邮件的另一个问题是他们经常更换。 如果你以其为关键词join其他表格,那么你将不得不更新其他表格,当整个客户公司改变他们的电子邮件(我已经看到发生了),这可能是相当的性能打击。

主键应该是唯一的不变的

电子邮件地址会像季节一样变化。 作为查找的辅助键很有用,但主键的select不佳。

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

  1. 进行联接时速度较慢。

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

  3. 一个电子邮件地址可能会改变,这将强制所有使用这个作为外键的logging被更新。 由于电子邮件地址不会经常更改,所以性能问题可能很小。 更大的问题是你必须确保提供它。 如果你必须编写代码,这是更多的工作,并介绍了错误的可能性。 如果你的数据库引擎支持“更新级联”,这是一个小问题。

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

  1. 您可能能够完全消除一些联接。 如果所有你需要的“主logging”是电子邮件地址,那么用一个抽象的整数键,你将不得不做一个连接来检索它。 如果密钥是电子邮件地址,那么您已经拥有它,并且join是不必要的。 这是否有助于你取决于这种情况出现的频率。

  2. 在进行即席查询时,人类很容易看到正在引用的主logging。 当试图追踪数据问题时,这可能是一个很大的帮助。

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

在我看来,这不是一个扣篮。 当我们倾向于使用自然键时,我倾向于使用自然键,因为它们只是更容易使用,在大多数情况下,缺点往往并不重要。

这是非常糟糕的。 假设一些电子邮件提供商停业。 用户将然后想要更改他们的电子邮件。 如果您使用电子邮件作为主键,用户的所有外键将复制该电子邮件,使其相当难以改变…

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

我不知道这是否可能是您的设置中的问题,但取决于您的RDBMS列的值可能区分大小写 。 PostgreSQL的文档说:“如果你声明一个列为UNIQUE或PRIMARY KEY,那么隐式生成的索引是区分大小写的”。 换句话说,如果您接受用户input作为主键的电子表格中的search,并且用户提供“John@Doe.com”,则不会find“john@doe.com”。

似乎没有人提到电子邮件地址可能被认为是私人的可能的问题。 如果电子邮件地址是主键,则最有可能的configuration文件页面URL将看起来像..../Users/my@email.com 。 如果您不想公开用户的电子邮件地址,该怎么办? 你必须find一些其他的方式来标识用户,可能是通过一个唯一的整数值来使URL像..../Users/1 。 那么你最终会得到一个唯一的整数值。

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

出于这个原因,devise可以适应。 自然键变成备用键 (UNIQUE,NOT NULL),并且使用代理/人工/技术键作为主键,在您的情况下可以是自动增量。

systempuntoout问,

如果有人想改变他的电子邮件地址呢? 你是否要改变所有的外键?

这就是级联的意义。

使用数字代理键作为主键的另一个原因与索引在您的平台中的工作方式有关。 例如,在MySQL的InnoDB中,表中的所有索引都有主键,因此您希望PK尽可能小(以速度和大小为准)。 与此相关的是,当主键顺序存储时,InnoDB速度更快,而string在这里没有帮助。

使用string作为备用密钥时需要考虑的另一件事是,使用实际string的哈希值可能会更快,而忽略某些字母的大写和小写。 (我真的在这里登陆,一边寻找一个参考,以确认我刚才说的;仍然看…)

是的,如果你使用一个整数代替它会更好。 您还可以将您的电子邮件列设置为唯一约束。

喜欢这个:

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

是的,这是一个不好的主键,因为你的用户将要更新他们的电子邮件地址。

整数主键更好的另一个原因是当你在不同的表中引用电子邮件地址。 如果地址本身是一个主键,那么在另一个表中,你必须使用它作为一个键。 所以你多次存储电子邮件地址。

我对postgres不太熟悉。 主键是一个很大的话题。 我在这个网站上看到了一些优秀的问题和答案(stackoverflow.com)。

我想你可能会有更好的性能,有一个数字主键,并在邮件列上使用UNIQUE INDEX。 电子邮件往往长度不同,可能不适合主键索引。

一些阅读这里和这里。

您的同事是正确的:为您的主键使用自动增量整数。

您可以在应用程序级别实现电子邮件唯一性,也可以将电子邮件地址列标记为唯一,并在该列上添加索引。

将字段添加为唯一字段只会在插入到表中时花费string比较,而不是在执行联接和外键约束检查时花费您的string比较。

当然,您必须注意,在数据库级别添加任何约束到您的应用程序可能会导致您的应用程序变得不灵活。 因为你的应用程序需要它是唯一的或非空的,所以在你使任何字段为“唯一”或“不为空”之前总是给予应有的考虑。

使用一个GUID作为主键……当你执行一个INSERT的时候,你可以通过你的程序生成它,而你不需要从服务器得到一个响应来找出主键。 它也将是独特的跨表和数据库,你不必担心如果你有一天截断表会发生什么,自动增量重置为1。

就个人而言,在devise数据库时,我不会使用任何信息作为主键,因为我很可能以后需要更改任何信息。 我提供主键的唯一原因是,从客户端进行大多数SQL操作是很方便的,而且我的select一直是自动递增整型。

我知道这有点晚了,但我想补充一点,人们放弃电子邮件帐户和服务提供商恢复地址,让另一个人使用它。

正如@HLGEM所指出的:“Jsmith@somecompany.com可以很容易地属于John Smith一年,Julia Smith两年之后。 在这种情况下,约翰·史密斯希望你的服务,你必须拒绝使用他的电子邮件地址或删除所有关于朱莉娅·史密斯的logging。

如果您必须删除logging,并根据当地法律将其与商业的财务状况相关联,则可能会发现自己处于热水中。

所以我绝对不会使用电子邮件地址,车牌等数据作为主键,因为无论他们看起来多么独特,他们都无法控制,并且可能会提供一些有趣的挑战,而您可能没有时间处理这些问题。

您可以使用整数主键提高性能。

你应该使用一个整数主键。 如果你需要email-column是唯一的,为什么不简单地在这个列上设置唯一索引?

如果你有一个非int值作为主键,那么在大数据上插入和检索将会非常慢。

这取决于表格。 如果您的表中的行代表电子邮件地址,那么电子邮件是最好的ID。 如果不是,那么电子邮件不是一个好的ID。

如果只是要求电子邮件是唯一的,那么你可以创build一个唯一的索引与该列。

电子邮件是一个很好的唯一索引候选人,但不是主键,如果它是主键,您将无法更改联系人的电子邮件地址,例如。 我认为你的连接查询也会变慢。

主键应该select一个静态属性。 由于电子邮件地址不是静态的,可以被多个候选人共享,因此将它们用作主键不是一个好主意。 此外,电子邮件地址通常是一定长度的string,可能会比我们想要使用的唯一标识符更大[len(email_address)> len(unique_id)],因此需要更多的空间,甚至最糟糕的是它们被存储多次作为外键。 因此会导致性能下降。

不要使用电子邮件地址作为主键,保持电子邮件的唯一性,但不要将其用作主键,使用用户名或用户名作为主键