VARCHAR是否已过时?

46
  1. VARCHAR不存储Unicode字符。
  2. NVARCHAR可以存储Unicode字符。
  3. 现代应用程序应始终兼容Unicode。
  4. NVARCHAR需要两倍的空间来存储。
  5. 由于存储空间非常廉价,因此第4点并不重要。

因此,在设计SQL Server数据库时,今天应始终使用NVARCHAR。

这是合理的推理吗?是否有人不同意任何前提条件? 今天选择VARCHAR而不是NVARCHAR的原因有哪些?


请参见此链接 https://dev59.com/9XVD5IYBdhLWcg3wQZUg - gbn
这并不是合理的推论,主要是由于无效的前提。第3项陈述过于宽泛。第4项在 SQL Server 2008 引入 PAGE 和 ROW 压缩以及 2008 R2 添加(自动/幕后)Unicode 压缩后部分已经过时(但压缩仅适用于企业版)。第5项是荒谬错误的。请参见我的答案:https://dev59.com/9XVD5IYBdhLWcg3wQZUg#32871477,了解详情。 - Solomon Rutzky
14个回答

51

将数据类型与要存储在列中的数据匹配。通过类似的论证,您可以说为什么不在NVARCHAR列中存储所有数据,因为数字和日期可以表示为数字字符串。

如果要存储在列中的数据的最佳匹配是VARCHAR,则使用它。


42

第四点并不重要,因为存储空间非常便宜。

这不仅涉及存储,还包括带宽、CPU、内存、备份、恢复和传输。所以要节约使用。


这里有我在这个回答中提到的链接:https://dev59.com/9XVD5IYBdhLWcg3wQZUg#198753 - gbn
在数据库中将存储定义为“NVARCHAR”并不意味着数据以UCS-2编码的Unicode形式“通过网络”发送。它可能通过网络传输,并且在应用程序内存中表示为UTF-8...这通常是“每个字符一个字节”。 - Dan H

27

我认为仍有不使用nvarchar的有效原因。

  • 存储空间很宝贵,例如在共享主机上或数据库非常庞大的情况下。
  • 性能至关重要。
  • 老系统的数据库已经存在使用varchar的表格(即褐色地带开发)。
  • 您需要与另一个只能理解单字节字符和/或varchar的旧系统集成。

然而,新开发应该尽可能使用nvarchar,特别是由于64位系统正在成为标准。此外,即使是小公司现在也更普遍地拥有全球业务。


64 位与 nvarchar 有什么关系? - Jeremy
2
双宽字符占用的内存是普通字符的两倍,但在64位系统上这不是太大的问题,因为它们可以访问比32位系统更多的RAM。在32位Windows上的32位SQL Server(在'08年仍然相当常见)只能使用2 GB RAM(无需跳过障碍)。 - Booji Boy

19

对于许多不同类型的列,你应该选择VARCHAR而不是NVARCHAR,这个选择应该是基于每一列的情况。

不需要额外开销的NVARCHAR的典型列包括:

ID类型的列:车牌号码、社会安全号码、患者病历标识等。

代码列:国际货币代码(USD、UKP等)、ISO国家代码(US、UK等)、语言代码(en-us等)、会计划分代码等。

邮政编码和邮编列。


11

我认为,相比较而言,nvarchars的比较成本要高于varchars,因此在真正不需要Unicode能力的地方,例如一些内部ID,使用varchars是完全有效的甚至是首选。

而存储成本仍然非常重要。如果你有数十亿行数据,那么这些“小”差别会很快变得非常大。


5
正如其他人指出的那样,这不仅仅涉及存储成本。
列的长度会影响每页的行数。每页行数越少,意味着可以放入缓存中的行数越少,性能就会下降。我假设在MSSQL中,一个被索引的NVARCHAR列将使用更多的索引空间。这意味着每个块中有更少的索引条目,因此索引中有更多的块,因此在扫描(或搜索)索引时需要更多的查找,从而减慢了索引访问速度。
因此,它在每个方面都会降低性能。如果你真的不在意(或者可以测量性能并且满意),那就没问题。但是,如果你确实需要存储Unicode字符,当然要使用NVARCHAR。
使用NVARCHAR在整个数据库中获得的可维护性可能超过了任何性能成本。

5
这种问题的答案通常都是:“视情况而定”。没有任何神奇的规则可以盲目遵循。即使在现代编程语言中使用GOTO也是可以被证明是有道理的:在支持循环和函数的语言中使用'goto'是否有优势?如果有,为什么? 因此,答案是:动动脑筋,考虑具体情况。在这种情况下,请记住,如果您的需求发生变化,您始终可以在数据库中从varchar转换为nvarchar。

4

我曾经看到nvarchar列被转换为varchar有两个原因:

  1. 应用程序正在使用MSSQL Express Edition,该版本的数据库大小限制为4GB。如果有许多数据库部署,切换到MSSQL Standard Edition将太昂贵,这将会在单租户Web应用程序或带嵌入式DBMS的应用程序中出现。更便宜的SQL2008 Web Edition可能会有所帮助。

  2. nvarchar(4000)不够用,但您不想要一个ntext列。因此,您将其转换为varchar(8000)。然而,在大多数情况下,您可能应该将其转换为nvarchar(max)。


3
您的第三点是无效的。只为一个国家设计的系统不必担心 Unicode,有些语言/产品根本不支持 Unicode 或仅部分支持。例如,TurboTax 只适用于美国(即使有加拿大版带有法语也仍然只是 LATIN-1),因此他们不需要或不必担心 Unicode 并且可能不支持它(我不知道他们是否支持,但即使他们支持,这只是一个例子)。
“今天的应用程序应始终与 Unicode 兼容。”
更准确地表达应该是:
“如果没有特殊需求来正确处理 Unicode,并且先前存在的代码库或任何其他应用程序部分不需要更新以支持它,则今天的应用程序应始终与 Unicode 兼容。”

1
我认为我总是会更加重视升级到Unicode可能带来的痛苦,而不是使用过多存储空间可能带来的痛苦。 - Edward Tanguay
1
作为一个非英语国家的成员(是的,世界上有很多这样的国家),其中语言包含变音符号,我可以说应用程序应该是Unicode兼容的。 - PiRX
1
我不明白为什么TurboTax只能是英文版的,即使它只限于美国使用也是如此... - Neil Williams
2
这似乎是一个有缺陷的假设。如果您的仅限美国的应用程序必须存储在其他国家出生的美国公民的姓名,并且其名称中有非ASCII字符,那会发生什么?假设仅因为该应用程序仅在美国或可能在加拿大使用,就不需要Unicode,这是愚蠢的。 - jalf
那显然该字符不会被输入。反过来说,假设现有产品和应用程序应该针对极端情况进行架构设计,而不是针对可能性,这种想法是愚蠢的。在这种情况下,使用YAGNI原则会更好。 - MetroidFan2002
显示剩余3条评论

2

存储费用比历史上任何时候都便宜,但如果您在给定的硬盘上可以存储两倍的数据,那是非常有吸引力的,不是吗?

此外,还有用于缓存的 RAM 和比硬盘昂贵得多的固态硬盘。如果您有数百万行数据,使用更紧凑的数据格式将非常有益。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接