与自动递增数字相比,电子邮件地址是否是主要的不良候选人?
我们的网络应用程序需要电子邮件地址在系统中是唯一的。所以,我想过用电子邮件地址作为主键。但是我的同事建议字符串比较比整数比较慢。
不使用电子邮件作为主键是否正确?
我们正在使用PostgreSQL
。
答案 0 :(得分:275)
字符串比较比int比较慢。但是,如果您只是使用电子邮件地址从数据库中检索用户,则无关紧要。如果您有多个连接的复杂查询,这很重要。
如果在多个表中存储有关用户的信息,则users表的外键将是电子邮件地址。这意味着您多次存储电子邮件地址。
答案 1 :(得分:173)
我还要指出,电子邮件是制作独特字段的不错选择,有人甚至小企业共享电子邮件地址。和电话号码一样,电子邮件可以重复使用。 Jsmith@somecompany.com可以很容易地属于约翰史密斯一年,朱莉亚史密斯可以两年后。
电子邮件的另一个问题是它们经常变化。如果你加入其他表作为密钥,那么你将不得不更新其他表,当整个客户公司更改他们的电子邮件时,这可能会受到很大影响(我已经看到了。)
答案 2 :(得分:96)
主键应唯一且 常量
电子邮件地址会像季节一样变化。可用作查找的辅助键,但主键的选择较差。
答案 3 :(得分:62)
使用电子邮件地址作为主键的缺点:
加入时速度较慢。
带有已发布外键的任何其他记录现在具有更大的值,占用更多磁盘空间。 (鉴于今天的磁盘空间成本,这可能是一个微不足道的问题,除非记录现在需要更长时间才能阅读。请参阅#1。)
电子邮件地址可能会更改,这会强制更新使用此作为外键的所有记录。由于电子邮件地址不会经常发生变化,因此性能问题可能很小。更大的问题是你必须确保提供它。如果你必须编写代码,这是更多的工作,并引入了错误的可能性。如果您的数据库引擎支持“on update cascade”,那么这是一个小问题。
使用电子邮件地址作为主键的优点:
您可以完全消除某些连接。如果您需要的“主记录”是电子邮件地址,那么使用抽象整数键,您必须进行连接才能检索它。如果密钥是电子邮件地址,那么您已经拥有它并且不需要加入。这对你有什么帮助取决于这种情况出现的频率。
当您进行即席查询时,人们很容易看到正在引用的主记录。在尝试追踪数据问题时,这可能是一个很大的帮助。
您几乎肯定需要电子邮件地址的索引,因此将其作为主键消除了一个索引,从而提高了插入的性能,因为它们现在只有一个索引要更新而不是两个。
在我的拙见中,无论如何,这不是一个扣篮。我倾向于在实用的时候使用自然键,因为它们更容易使用,在大多数情况下,这些缺点往往并不重要。
答案 4 :(得分:12)
我不知道这可能是您设置中的问题,但根据您的RDBMS,列的值可能区分大小写。 PostgreSQL文档说:“如果将列声明为UNIQUE或PRIMARY KEY,则隐式生成的索引区分大小写”。换句话说,如果您接受用电子邮件作为主键的表格中的搜索用户输入,并且用户提供“John@Doe.com”,则您将找不到“john@doe.com”。
答案 5 :(得分:12)
非常糟糕。假设某些电子邮件提供商破产。然后,用户将要更改他们的电子邮件。如果您使用电子邮件作为主键,用户的所有外键都将复制该电子邮件,这使得它很难改变......
......我甚至还没有开始谈论性能方面的考虑。
答案 6 :(得分:10)
似乎没有人提到电子邮件地址可能被视为私有的可能问题。如果电子邮件地址是主键,则配置文件页面网址很可能看起来像..../Users/my@email.com
。如果您不想公开用户的电子邮件地址怎么办?您必须找到一些其他识别用户的方法,可能通过一个唯一的整数值来制作像..../Users/1
这样的网址。然后你最终得到一个唯一的整数值。
答案 7 :(得分:8)
在logical level,电子邮件是自然密钥。 在 physical 级别,如果您使用的是关系数据库,则自然键不适合作为主键。原因主要是其他人提到的性能问题。
因此,可以调整设计。自然键变为alternate key(UNIQUE,NOT NULL),并使用surrogate/artificial/technical key作为主键,在您的情况下可以是自动增量。
systempuntoout问,
如果有人想要更改他的电子邮件地址怎么办?你打算改变所有的外键吗?
这就是cascading的用途。
使用数字代理键作为主键的另一个原因与索引在您的平台中的工作方式有关。例如,在MySQL的InnoDB中,表中的所有索引都预先设置了主键,因此您希望PK尽可能小(对于速度和大小的清醒)。与此相关的是,当主键按顺序存储时,InnoDB更快,并且字符串对此没有帮助。
使用字符串作为备用键时要考虑的另一件事是,使用您想要的实际字符串的哈希可能会更快,跳过某些字母的大写和小写的情况。 (我实际上是在寻找参考来确认我刚才所说的内容时仍然来到这里;仍在寻找......)
答案 8 :(得分:4)
是的,如果你改用整数会更好。您还可以将电子邮件列设置为唯一约束。
像这样:CREATE TABLE myTable(
id integer primary key,
email text UNIQUE
);
答案 9 :(得分:4)
是的,这是一个错误的主键,因为您的用户想要更新他们的电子邮件地址。
答案 10 :(得分:3)
我对postgres不太熟悉。主键是一个很大的主题。我在这个网站上看到了一些很好的问题和答案(stackoverflow.com)。
我认为您可以通过使用数字主键并在电子邮件列上使用UNIQUE INDEX来获得更好的性能。电子邮件的长度往往不同,可能不适合主键索引。
答案 11 :(得分:3)
整数主键更好的另一个原因是当您在不同的表中引用电子邮件地址时。如果地址本身是主键,则在另一个表中,您必须将其用作键。因此,您可以多次存储电子邮件地址。
答案 12 :(得分:3)
就个人而言,在设计数据库时我没有使用任何主键信息,因为我很可能需要稍后更改任何信息。我提供主键的唯一原因是,从客户端进行大多数SQL操作很方便,而我的选择一直是自动递增整数类型。
答案 13 :(得分:2)
您的同事是对的:为您的主键使用自动增量整数。
您可以在应用程序级别实现电子邮件唯一性,也可以将电子邮件地址列标记为唯一,并在该列上添加索引。
将字段添加为唯一将仅在插入到该表时进行字符串比较,而不是在执行连接和外键约束检查时。
当然,您必须注意,在数据库级别向应用程序添加任何约束都可能导致您的应用程序变得不灵活。在将任何字段设置为“唯一”或“非空”之前,请始终给予充分考虑,因为您的应用程序需要它是唯一的或非空的。
答案 14 :(得分:2)
我知道这是一个迟到的条目,但我想补充一点,人们放弃电子邮件帐户,服务提供商恢复地址,允许其他人使用它。
正如@HLGEM指出的那样,“Jsmith@somecompany.com可以很容易地属于约翰史密斯一年,而朱莉亚史密斯可以在两年后。”在这种情况下,John Smith需要您的服务,您必须拒绝使用他的电子邮件地址或删除所有与Julia Smith有关的记录。
如果您必须删除记录,并且根据当地法律与业务的财务历史相关,您可能会发现自己处于热水中。
所以我永远不会使用电子邮件地址,车牌等数据作为主键,因为无论它们看起来多么独特,它们都是您无法控制的,并且可以提供一些您可能没有时间处理的有趣挑战
答案 15 :(得分:2)
使用GUID作为主键...这样,当您执行INSERT时,可以从程序生成它,并且您不需要从服务器获取响应以找出主键是什么。它在表和数据库中也是独一无二的,你不必担心如果你某天截断表并且自动增量重置为1会发生什么。
答案 16 :(得分:1)
主键应选择静态属性。由于电子邮件地址不是静态的,并且可以由多个候选人共享,因此将它们用作主键并不是一个好主意。此外,电子邮件地址通常是一定长度的字符串,可能大于我们想要使用的唯一ID [len(email_address)> len(unique_id)],因此它需要更多空间,甚至最糟糕的是它们作为外来存储多次键。因此,它会导致性能下降。
答案 17 :(得分:1)
您可以使用整数主键来提升性能。
答案 18 :(得分:1)
您可能需要考虑任何适用的数据法规。电子邮件是个人信息,例如,如果您的用户是欧盟公民,那么在GDPR下,他们可以指示您从记录中删除其信息(请记住,无论您身在哪个国家/地区,该信息都适用。
如果出于引用完整性或历史原因(例如审核)需要将记录本身保留在数据库中,则使用代理键将使您可以将所有个人数据字段都设为NULL。如果他们的个人数据是主键,这显然不那么容易
答案 19 :(得分:1)
如果您将非int值作为主键,那么大数据上的插入和检索将非常慢。
答案 20 :(得分:1)
您应该使用整数主键。如果您需要将email-column设置为唯一,为什么不在该列上设置唯一索引?
答案 21 :(得分:0)
电子邮件是一个很好的唯一索引候选者,但不是主键,如果它是主键,您将无法更改联系人的电子邮件地址。 我认为你的连接查询也会变慢。
答案 22 :(得分:0)
如果只是要求电子邮件是唯一的,那么您可以使用该列创建唯一索引。
答案 23 :(得分:0)
这取决于表格。如果表中的行代表电子邮件地址,则电子邮件是最佳ID。如果没有,那么电子邮件不是一个好的ID。
答案 24 :(得分:0)
不要将电子邮件地址用作主键,将电子邮件保留为唯一,但不要将其用作主键,请使用用户ID或用户名作为主键