我应以哪种数据类型在数据库中存储电子邮件地址?


44

我知道254个字符的电子邮件地址是有效的,但是我研究过的实现倾向于使用varchar(60)到varchar(80)或等效的电子邮件。例如:此SQL Server建议使用varchar(80)或此Oracle示例

是否有理由不使用完整的254个字符的最大值?按照定义,varchar不会仅使用所需的存储量来保存数据吗?

是否存在重大的性能隐含/折衷,导致如此多的实现使用少于254个可能的字符?

Answers:


45

我一直都习惯VARCHAR(320)。这就是为什么。该标准规定了以下限制:

  • “本地部分”(用户名)的64个字符。
  • @符号为1个字符。
  • 域名的255个字符。

现在,有些人会说您需要提供更多支持。有些人还会说,您需要支持Unicode域名(这意味着您必须切换到NVARCHAR)。尽管标准可能在此期间发生变化(自从我开始玩皮肤以来已经有一段时间了),但我非常有信心,这时世界上大多数服务器将不接受Unicode电子邮件地址,而且我敢肯定许多服务器在创建和/或接受超过320个字符的地址时会遇到问题。

也就是说,如果愿意,您可以为最坏的情况做准备(如果您在SQL Server 2008 R2或更高版本中使用数据压缩,则将从Unicode压缩中受益,这意味着您只需为实际需要的字符支付2字节的罚款它)。这样,您可以将列的宽度设置为所需的宽度,并且可以让人们在其中填充任何过长的垃圾-如果他们像给别人一样给您垃圾,他们就不会收到电子邮件如果插入失败,将收到一封电子邮件。问题是,如果你让无效的垃圾中,必须处理它。不管您使用什么大小-如果有人尝试将400个字符填充到320个字符的列中,那么有人将尝试将1025个字符填充到1024个字符的列中。没有理智的人应该有一个大于320个字符的电子邮件地址,除非他们使用它来明确测试系统边界。

但是,不要再对此提出意见了,而要停止寻找其他实现的指导(在这种情况下,您所引用的对象就不会费心去做自己的功课,只是从他们那里选出了数字,好吧,您知道) 。您可以直接访问该标准 -确保您参考最新版本,至少要支持该版本,并且始终处于标准之上,以便您可以适应规范的更改。


编辑感谢@ypercube在聊天中进行ping操作。

顺便说一句,也许您不想首先将整个地址转储到单个列中。规范化可能表明您不希望存储@hotmail.com1,500万次,而使用更细小的FK int可以很好地工作并且没有可变长度列的额外开销。您还可以将用户名标准化为,john.smith@hotmail.comjohn.smith@gmail.com共享一个通用用户名-他们彼此不认识,但是您的数据库对此并不在乎。

我在这里谈论了其中一些:

http://www.mssqltips.com/sqlservertip/2657/storing-email-addresses-more-ficientlyly-in-sql-server/

http://www.mssqltips.com/sqlservertip/2671/storing-email-addresses-more-ficientlyly-in-sql-server--part-2/

但是,这给上面的254个字符的限制带来了挑战,因为对于将有效的255个字符的域与有效的1个字符的localpart组合在一起时似乎没有达成共识。世界各地的大多数服务器都应接受此限制,但似乎违反了此254个字符的限制。因此Domains,当该域可以重新用作有效的255个字符的URL 时,您是否创建了一个对地址长度的人为限制较低的表?


我喜欢这种方法,但是电子邮件的唯一性呢?如何管理?
罗伯托·里兹

2
@RobertoRizzi DomainID + LocalPart的组合上的唯一约束或主键,反之亦然。
亚伦·伯特兰

5

这个决定有一些考虑因素。首先,最重要的是使用当前和将来的数据必须符合的必要限制的预测。varchar(1024)当您只存储超过32个字符的字符串(强调should关键字)时,不想将每个字符串列数据类型都设置为有一个原因。

如果您存在某种漏洞,其中所有电子邮件都被修改为255个字符,那么对页面拆分的性能影响可能很大。这看起来可能与众不同,很可能是这样,但是您需要根据业务需求调整数据大小。就像数据库与应用程序争论中的古老约束一样,我坚信数据类型限制和允许的值也应在数据层强制实施。

这引出我的下一个观点。数据库很可能只是数据层。应用程序层利用什么?例如,如果您有一个只能输入80个字符的电子邮件地址的应用程序,为什么要将数据类型设置为更大?业务需要回答两个问题:

  1. 什么是什么?
  2. 什么应该是什么?

只有这样,您才能得到答案。

按照定义,varchar不会仅使用所需的存储量来保存数据吗?

是的,没有。可变长度数据将存在某种偏移以记录其长度。


3

RFC 5321(当前的SMTP规范,已淘汰RFC2821)规定:

用户名或其他本地部分的最大总长度为64个八位位组。域名或号码的最大总长度为255个八位字节

因此64 + 255 + @符号表示VARCHAR(320)。您可能永远不需要那么多,但是为了以防万一,拥有它是安全的。



1

VARCHAR的任何变体仅在数据块中使用所需的空间。与使用固定长度CHAR浪费的空间相比,用于存储长度的额外字节是微不足道的。

由于VARCHAR列的长度实际上是“最大长度”,因此在任何情况下都应将其设置为大于可能的最大长度。仅使用每行需要的空间。然后应使用滚动字段或基于典型值的任何有意义的方法设计应用程序。

数据库设计就像一张纸一样,它为大小设置了硬性限制。纸页无法放大。以此类推,应用程序就像打印在页面上的表格。要调整我们可以容纳多少数据,可以做很多事情。

尽管增加VARCHAR大小的命令看起来很简单,并且可以立即在一个小表上运行,但是在具有数千行或更多行的表上执行此操作可能需要某种数据库静默,同时重新生成所有数据和索引块。一种方法是将所有内容复制到具有较大列的新表中。无论使用哪种技术,这都是一件大毛病交易。因此,一旦加载了生产表,您应该考虑VARCHAR列大小在很大程度上是不变的。


1

作为对此处已有出色答案的评论:

首先,如果您创建的字段为as,varchar(240)并且希望以后将其更改为更长的字段,例如varchar(320),则此更改对数据库服务器来说应该是微不足道的操作-当然,这取决于您的数据库产品。

alter table Schema.Object alter column EmailAddress varchar(320) ;

其次,根据平均行大小和页面大小,使用varchar(320)代替varchar(240)可能不会更改分配的页面数(表实际占用的磁盘空间)。

第三,上面的某人谈到了验证电子邮件地址。我认为,只有一种确定的方法可以验证电子邮件地址,即向其发送电子邮件。:-)


0

VARCHAR是用于电子邮件地址的最佳数据类型,因为电子邮件的长度差异很大。NVARCHAR也是一种替代方法,但我建议仅在电子邮件地址包含扩展字符的情况下使用它,并记住与VARCHAR相比,它需要两倍的存储空间。

在我的环境中,我们使用varchar(70),因为我碰到的最长字符接近60-70个字符长,但这也取决于您公司的客户群。另外,作为一个旁注,请确保已就电子邮件地址的有效性进行了一些电子邮件验证检查。.例如,使用检查约束或CHARINDEX


0

使用SQL DOMAIN

如果您使用的是Enterprise Database服务器,则应该以某种方式将电子邮件地址存储为DOMAIN具有一定程度的有效性。域在SQL规范中指定

域是一个命名的用户定义对象,可以在某些可以指定数据类型的地方将其指定为数据类型的替代。域由数据类型(可能是默认选项)和零个或多个(域)约束组成。

例如,免费和开源的PostgreSQL支持这一点,除非对规范的实施有任何限制,否则该列本身包含有效的电子邮件。您可以例如。

  • DOMAIN根据电子邮件的HTML5规范创建自定义。
  • 或者,通过电子邮件的RFC822,RFC2822,RFC5322规范。
  • 创建一个自定义DOMAIN,以在检查时检查服务器是否有MX记录。

我在这个针对PostgreSQL的答案中评估了这些选项

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.