是否有理由不使用最多254个字符的完整字符?按照定义,varchar不会只使用所需的存储空间来保存数据吗?
是否存在重大的性能影响/折衷,导致很多实现使用少于254个可能字符?
#1 楼
我一直使用VARCHAR(320)
。这就是为什么。该标准规定了以下限制:“本地部分”(用户名)为64个字符。
@
符号为1个字符。
255个字符为域名。
现在,有些人会说您需要提供更多支持。有些人还会说,您需要为域名支持Unicode(这意味着您必须切换到
NVARCHAR
)。尽管标准可能会在此期间发生变化(自从我拥有皮肤以来已经有一段时间了),但是我非常有信心在这个时候世界上大多数服务器将不接受Unicode电子邮件地址,而且我相信许多服务器在创建和/或接受超过320个字符的地址时会遇到问题。 这就是说,如果您愿意,现在可以为最坏的情况做准备(如果您在SQL Server 2008 R2或更高版本中使用数据压缩,则可以从Unicode压缩中受益,这意味着您只需支付实际需要的字符为2个字节的罚款)。这样,您可以将栏目设置为所需的宽度,并且可以让人们在其中填充任何过长的垃圾-如果他们像给别人一样给您垃圾,他们将不会收到电子邮件如果插入失败,将收到一封电子邮件。问题是,如果让无效的垃圾进入,则必须对其进行处理。不管您使用什么大小-如果有人尝试将400个字符填充到320个字符的列中,则有人尝试将1025个字符填充到1024个字符的列中。没有理智的人应该有一个大于320个字符的电子邮件地址,除非他们使用它来显式测试系统边界。
但是,不要再对此提出意见了,而要停止寻找其他实现的指导(在这种情况下,您所引用的对象就不会费心去做自己的功课,只是从他们那儿挑选了一些数字,好吧,您知道) 。您可以直接访问该标准-确保您参考最新版本,至少要支持该版本,并保持在标准之上,以便您可以适应规范的更改。 > EDIT感谢@ypercube在聊天中执行ping操作。规范化可能建议您不要存储
@hotmail.com
1,500万次,而使用更细小的FK int可以正常工作,而不必承担可变长度列的额外开销。您还可以规范化用户名,因为john.smith@hotmail.com
和john.smith@gmail.com
共享一个通用的用户名-它们彼此不认识,但是您的数据库不在乎。 br /> http://www.mssqltips.com/sqlservertip/2657/storing-email-addresses-more-efficiently-in-sql-server/
http:// www .mssqltips.com / sqlservertip / 2671 / storing-email-addresses-更加高效地在sql-server中-第2部分/
这给上述254个字符的限制带来了挑战,因为当将有效的255个字符的域与有效的1个字符的localpart组合在一起时,似乎不会达成共识。世界各地的大多数服务器都应该接受此限制,但似乎违反了此254个字符的限制。那么,当该域可以重新用作有效的255个字符的URL时,您是否创建了一个对地址长度的人为限制较低的
Domains
表?#2 楼
此决定有一些注意事项。首先,最重要的是使用当前和将来的数据必须符合的必要限制的预测。当您只存储不超过32个字符的字符串时,您不希望将每个字符串列数据类型都设置为varchar(1024)
是有原因的(强调should关键字)。如果存在某种漏洞,其中所有电子邮件都被修改为255个字符,那么可能会对页面拆分产生长期的性能影响。这看起来可能与众不同,很可能是这样,但是您需要根据业务需求调整数据大小。就像数据库与应用程序辩论中的古老约束一样,我坚信数据类型限制和允许值也应在数据层强制实施。这使我想到了下一点。数据库很可能只是数据层。应用程序层利用什么?例如,如果您有一个只能输入80个字符的电子邮件地址的应用程序,那么为什么要将数据类型设置为更大?业务需要回答两个问题:
是什么?
应该是什么?
只有这样,您才能得到答案。
按照定义,varchar不会使用所需的存储空间来存储数据吗?可变长度数据将存在某种偏移以记录其长度。
#3 楼
RFC 5321(当前SMTP规范,已淘汰RFC2821)规定:用户名或其他本地部分的最大总长度为64个
八位位组。
域名或数字的最大总长度为255个八位字节
因此64 + 255 + @符号表示VARCHAR(320)。您可能永远不需要那么多,但是为了以防万一,它是安全的。
评论
正确的限制是254。rfc-editor.org/errata_search.php?rfc=3696&eid=1690
–尼尔·麦圭根(Neil McGuigan)
2013年12月19日在18:32
#4 楼
VARCHAR的任何变体仅在数据块中使用所需的空间。与使用固定长度CHAR浪费的空间相比,用于存储长度的额外字节是微不足道的。在任何情况下都大于最大长度。仅使用每行需要的空间。然后,应使用滚动字段或基于典型值的任何有意义的东西来设计应用程序。纸页无法放大。以此类推,应用程序就像打印在页面上的表格。可以做很多事情来调整表格中可以容纳的数据量。具有数千行或更多行的表在重新生成所有数据和索引块时可能需要某种数据库静默。一种方法是将所有内容复制到具有较大列的新表中。无论使用哪种技术,这都是一件大毛病交易。因此,一旦加载了生产表,您应该考虑VARCHAR列大小在很大程度上是不变的。#5 楼
作为对此处已经存在的出色答案的评论:首先,如果您将字段创建为
varchar(240)
,并且想要稍后将其更改为更长的字段(例如varchar(320)
),则此更改应该是一件小事在数据库服务器上-当然取决于数据库产品。alter table Schema.Object alter column EmailAddress varchar(320) ;
其次,根据平均行大小和页面大小,使用
varchar(320)
而不是varchar(240)
可能不会更改分配的页数(表实际占用的磁盘空间)。第三,上面的某人谈到了验证电子邮件地址。我认为,只有一种确定的方法可以验证电子邮件地址,即向其发送电子邮件。 :-)
#6 楼
VARCHAR是用于电子邮件地址的最佳数据类型,因为电子邮件的长度差异很大。 NVARCHAR也是一种替代方法,但我建议仅在电子邮件地址包含扩展字符的情况下使用它,并记住与VARCHAR相比,它需要两倍的存储空间。请使用varchar(70),因为我遇到的最长字符大约为60-70个字符,但这也取决于您公司的客户群。
此外,请确保您拥有一些电子邮件验证就地检查电子邮件地址的有效性。例如使用检查约束或CHARINDEX
#7 楼
使用SQLDOMAIN
如果使用的是企业数据库服务器,则应该以某种方式将电子邮件地址存储为
DOMAIN
,并具有一定的有效性。域是在SQL规范中指定的。域是一个命名的用户定义对象,可以在可以指定数据类型的某些位置将其指定为数据类型的替代。域由数据类型(可能是默认选项)和零个或多个(域)约束组成。
例如,免费和开源的PostgreSQL支持这一点,除非您在实施规范时,该列本身包含有效的电子邮件。例如,您可以..
在电子邮件的HTML5规范上创建自定义
DOMAIN
。或者在电子邮件的RFC822,RFC2822,RFC5322规范上创建。创建一个自定义的
DOMAIN
,以在检查时检查服务器是否有MX记录。
评论
我喜欢这种方法,但是电子邮件的唯一性呢?如何管理?
– Roberto Rizzi
18年4月10日在11:03
@RobertoRizzi DomainID + LocalPart的组合上的唯一约束或主键,反之亦然。
–亚伦·伯特兰(Aaron Bertrand)
18年4月10日在11:42