与自动递增的数字相比,电子邮件地址是否是主要的候选地址?
我们的Web应用程序需要电子邮件地址在系统中唯一。因此,我想到了使用电子邮件地址作为主键。但是我的同事建议,字符串比较将比整数比较慢。
不使用电子邮件作为主键是正确的理由吗?
我们正在使用PostgreSQL
。
与自动递增的数字相比,电子邮件地址是否是主要的候选地址?
我们的Web应用程序需要电子邮件地址在系统中唯一。因此,我想到了使用电子邮件地址作为主键。但是我的同事建议,字符串比较将比整数比较慢。
不使用电子邮件作为主键是正确的理由吗?
我们正在使用PostgreSQL
。
Answers:
字符串比较比int比较慢。但是,如果您只是使用电子邮件地址从数据库中检索用户,这并不重要。如果您有包含多个联接的复杂查询,这很重要。
如果您在多个表中存储有关用户的信息,则用户表的外键将是电子邮件地址。这意味着您多次存储了电子邮件地址。
我还要指出,电子邮件是创建唯一字段的错误选择,有些人甚至是小型企业都共享电子邮件地址。就像电话号码一样,电子邮件也可以重复使用。一年后,Jsmith @ somecompany.com可以轻松属于John Smith,两年后可以轻松属于Julia Smith。
电子邮件的另一个问题是它们经常更改。如果您要使用其他键加入其他表,那么您还必须更新其他表,这在整个客户公司更改其电子邮件时都会对性能造成很大的影响(我见过这种情况)。
主键应唯一且恒定
电子邮件地址会随着季节的变化而变化。用作查找的辅助键,但为主键的选择不理想。
使用电子邮件地址作为主键的缺点:
加入时变慢。
现在,任何其他带有已发布外键的记录都将具有更大的值,从而占用更多的磁盘空间。(考虑到今天的磁盘空间成本,这可能是一个琐碎的问题,但就目前而言,读取记录需要更长的时间。请参阅#1。)
电子邮件地址可能会更改,这将强制更新所有使用此地址作为外键的记录。由于电子邮件地址不会经常更改,因此性能问题可能很小。更大的问题是您必须确保提供它。如果您必须编写代码,则这需要更多工作,并且可能会出现错误。如果您的数据库引擎支持“按更新级联”,则是一个小问题。
使用电子邮件地址作为主键的优点:
您也许可以完全消除一些联接。如果您仅需要“主记录”中的电子邮件地址,则必须使用抽象整数键进行联接才能检索它。如果密钥是电子邮件地址,则您已经拥有它,因此不需要加入。这是否对您有帮助,取决于这种情况出现的频率。
当您进行临时查询时,人们很容易看到正在引用的主记录。尝试查找数据问题时,这可能是一个很大的帮助。
几乎可以肯定,无论如何,您都将在电子邮件地址上需要一个索引,因此使其成为主键可以消除一个索引,从而提高了插入的性能,因为它们现在仅需要更新一个索引而不是两个索引。
以我的拙见,这也不是灌篮高手。我倾向于在可用的自然键时使用自然键,因为它们更易于使用,并且缺点在大多数情况下并没有太大关系。
真不好 假设某些电子邮件提供商停业了。然后,用户将要更改其电子邮件。如果您已使用电子邮件作为主键,则用户的所有外键都将复制该电子邮件,这真是很难更改...
...而且我什至还没有开始谈论性能方面的考虑。
我不知道这可能不是您设置中的问题,但是取决于您的RDBMS,列的值可能区分大小写。PostgreSQL文档说:“如果将一列声明为UNIQUE或PRIMARY KEY,则隐式生成的索引区分大小写”。换句话说,如果您接受用户输入以电子邮件作为主键的表中的搜索,并且用户提供“ John@Doe.com”,则不会找到“ john@doe.com”。
似乎没有人提到电子邮件地址可能被视为私有的可能问题。如果电子邮件地址是主键,则配置文件页面URL很可能看起来像..../Users/my@email.com
。如果您不想公开用户的电子邮件地址怎么办?您必须找到其他识别用户的方式,可能是通过唯一的整数值来创建类似的URL ..../Users/1
。然后,您最终将获得唯一的整数值。
从逻辑上讲,电子邮件是自然键。在物理级别上,假设您使用的是关系数据库,那么自然键和主键就不太适合。原因主要是其他人提到的性能问题。
因此,可以对设计进行调整。自然键成为备用键(UNIQUE,NOT NULL),并且您使用替代/人造/技术键作为主键,在您的情况下可以自动递增。
systempuntoout问,
如果有人想更改他的电子邮件地址怎么办?您还要更改所有外键吗?
这就是级联的目的。
使用数字代理键作为主键的另一个原因与平台中索引的工作方式有关。例如,在MySQL的InnoDB中,表中的所有索引都预先添加了主键,因此您希望PK尽可能小(出于速度和大小的考虑)。同样与此相关的是,当按主键顺序存储时,InnoDB更快,而字符串则无济于事。
使用字符串作为备用键时要考虑的另一件事是,使用所需的实际字符串的哈希值可能会更快,从而跳过了某些字母的大写和小写之类的事情。(实际上,我在寻找参考信息以确认我刚才所说的内容时落在了这里;仍在寻找...)
是的,最好使用整数代替。您还可以将电子邮件列设置为唯一约束。
像这样:
CREATE TABLE myTable(
id integer primary key,
email text UNIQUE
);
您的同事是正确的:将自动递增的整数用作主键。
您可以在应用程序级别实现电子邮件唯一性,也可以将电子邮件地址列标记为唯一,然后在该列上添加索引。
仅在将字段插入表中时,将字段添加为唯一字段会花费字符串比较的费用,而在执行联接和外键约束检查时则不会。
当然,您必须注意,在数据库级别向应用程序添加任何约束都会导致应用程序变得不灵活。在将任何字段设置为“唯一”或“不为空”之前,请务必给予应有的考虑,因为您的应用程序需要该字段是唯一或非空的。
将GUID用作主键...这样,您可以在执行INSERT时从程序中生成它,而无需从服务器获取响应即可知道主键是什么。它在表和数据库中也将是唯一的,并且您不必担心如果某天截断表并将自动增量重置为1会发生什么情况。
我知道这有点晚了,但我想补充一点,人们放弃了电子邮件帐户,服务提供商恢复了该地址,允许其他人使用它。
正如@HLGEM所指出的那样:“ Jsmith@somecompany.com可以很容易地在一年后归属于John Smith,而在两年后可以归属于Julia Smith。” 在这种情况下,如果约翰·史密斯(John Smith)需要您的服务,您要么拒绝使用他的电子邮件地址,要么删除所有与朱莉娅·史密斯(Julia Smith)有关的记录。
如果您必须删除记录,并且它们与取决于当地法律的企业财务历史相关,则您可能会陷入困境。
因此,我绝不会将电子邮件地址,车号牌等数据用作主键,因为无论它们看起来多么独特,它们都将超出您的控制范围,并且可能会带来一些您可能没有时间处理的有趣挑战。
如果您有一个非int值作为主键,那么对大数据的插入和检索将非常慢。
这取决于表。如果表中的行代表电子邮件地址,则电子邮件是最佳ID。如果不是,则电子邮件不是一个好的ID。