46
  1. VARCHAR 不存储 Unicode 字符。
  2. NVARCHAR 确实存储 Unicode 字符。
  3. 今天的应用程序应该始终与 Unicode 兼容。
  4. NVARCHAR 需要两倍的空间来存储它。
  5. 第 4 点无关紧要,因为存储空间非常便宜。

Ergo:今天在设计 SQL Server 数据库时,应该始终使用 NVARCHAR。

这是合理的推理吗?有人不同意任何前提吗?今天有什么理由选择 VARCHAR 而不是 NVARCHAR 吗?

4

14 回答 14

51

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

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

于 2008-11-23T06:54:08.470 回答
41

第 4 点无关紧要,因为存储空间非常便宜。

它不仅仅是存储,还有带宽——CPU、内存、备份、恢复、传输。养护。

于 2008-11-23T06:48:43.553 回答
27

我想说仍然有充分的理由不使用 nvarchar。

  • 存储空间非常宝贵,例如在共享主机上或数据库 非常巨大。
  • 性能至关重要。
  • 棕地开发(即数据库具有使用 varchar 的现有表)。
  • 您正在与另一个只理解单字节字符和/或 varchar 的旧系统集成。

然而,新的开发可能应该使用 nvarchar esp。因为 64 位系统正在成为常态。此外,公司(甚至是小公司)现在更普遍地全球化。

于 2008-11-23T06:15:58.673 回答
19

对于许多不同类型的列,您应该选择 VARCHAR 而不是 NVARCHAR,并且选择将基于每列。

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

ID 类型列:车牌、SSN、患者图表标识符等。

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

邮政编码和邮政编码列。

于 2008-11-24T05:22:23.600 回答
11

我相信 nvarchars 的比较比 varchars 成本更高,因此在您确实不需要 unicode 功能的地方(例如,对于某些内部 ID),它是完全有效的,甚至是首选。

存储成本仍然很重要。如果您有数十亿行,那么这些“小”差异会很快变大。

于 2008-11-23T07:32:56.613 回答
5

正如其他人所指出的,这不仅仅是存储成本。

列的长度会影响每页的行数。每页的行数越少意味着可以放入缓存的行数越少,这会降低性能。我假设在 MSSQL 中,被索引的 NVARCHAR 列将占用索引中的更多空间。这意味着每个块的索引条目更少,因此索引中的块更多,因此在扫描(或搜索)索引时需要更多的搜索,这也会减慢索引访问。

所以它会在每一个方面失去你的表现。如果您真的不在乎(或者可以衡量性能并对此感到满意,当然),那很好。但是,如果您确实需要存储 unicode 字符,当然可以使用 NVARCHAR。

我可能是通过在整个数据库中使用 NVARCHAR 获得的可维护性超过了任何性能成本。

于 2008-11-23T07:29:25.840 回答
5

这类问题总是有相同的答案:这取决于. 没有你应该盲目遵循的神奇规则。甚至在现代编程语言中使用 GOTO 也是合理的:在支持循环和函数的语言中使用“goto”是否有利?如果是这样,为什么?

所以答案是:用你的头脑思考特定的情况。在这种特殊情况下,请记住,如果您的需求发生变化,您始终可以在数据库中将 varchar 转换为 nvarchar。

于 2008-11-23T08:44:50.963 回答
4

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

  1. 应用程序使用的是 MSSQL Express Edition,它有 4GB 的数据库大小限制。如果有许多数据库部署,切换到 MSSQL 标准版将太昂贵,就像在单租户 web 应用程序或具有嵌入式 DBMS 的应用程序中一样。更便宜的 SQL2008 网络版可以在这里提供帮助。

  2. nvarchar(4000) 是不够的,但你不想要一个 ntext 列。所以你转换为 varchar(8000)。但是,在大多数情况下,您可能应该转换为 nvarchar(max)。

于 2008-11-23T10:15:26.660 回答
3

您的第 3 点无效。专为单一国家使用而设计的系统不必担心 unicode,而且使用中的某些语言/产品根本不支持或仅部分支持 unicode。例如,TurboTax仅适用于美国(即使使用法语的加拿大版本仍然只是 LATIN-1),所以他们不需要或不必担心 unicode 并且可能不支持它(我不知道他们是否这样做,但即使他们这样做,这也只是一个例子)。

“今天的应用程序应该始终与 Unicode 兼容。”

可能更有效的表示为:

“今天的应用程序应该始终与 Unicode 兼容,如果不需要发生任何特殊情况来正确处理 Unicode,并且以前存在的代码库或应用程序的任何其他部分不需要专门更新以支持它”

于 2008-11-23T06:24:52.413 回答
2

存储比以往任何时候都便宜,但是如果您可以在给定的硬盘驱动器上存储两倍的数据,那还是很有吸引力的,不是吗?

还有用于缓存的 RAM 和固态驱动器,它们都比硬盘驱动器贵得多。当您拥有数百万行时,使用更紧凑的数据格式是有益的。

于 2008-11-23T06:24:03.057 回答
2

有没有办法让您的数据库服务器使用 UTF-8 作为编码?然后,您可以获得大多数 ASCII 加载的低存储空间的好处,以及存储 Unicode 范围内的任何内容的能力,以便可以进行扩展。

我会要求您的数据库供应商也支持 UTF-8 作为VARCHARSQL 类型的编码。我不知道其他数据库服务器是如何做到的,但我知道您至少可以在 MySQL 和 PostgreSQL中的VARCHAR和字段中使用 UTF-8。TEXT

尽管如此,使用 UTF-16 编码字段的唯一原因是您必须与将在 UTF-16 输入上中断的应用程序进行交互。这将是大多数旨在处理 ASCII 或 ISO-8815 文本编码的遗留应用程序,这将更好地处理 UTF-8。

于 2008-11-23T07:08:59.737 回答
2

我的倾向是“使用 NVARCHAR”作为默认值......但@CadeRoux 有一个很好的观点:如果您确定数据将永远不会包含 ASCII 以外的任何内容 - 就像美国车牌一样 - VARCHAR 可能会为您节省一点点成本。

我会说他的好声明的另一面是“不要使用 NVARCHAR”来处理任何有名字(人、街道、地点)或自然语言文本(电子邮件、聊天、文章、博客帖子、照片说明)的东西。否则,您的“名字”列将无法正确编码“François”或“José”,并且您的文本列将不允许带有“外国”变音符号的文本,或者 - 就此而言 - 非常常见的美国字符,如分号“¢”,段落标记“¶”,项目符号“•”。(因为这些都不是ASCII 字符,并且没有好的标准方法将它们放入 VARCHAR 字段。相信我:你会伤害自己。)

在我从事的任何项目中,我从来没有因为使用 NVARCHAR 而被责骂,因为我“在磁盘空间上浪费了太多的公司资金”。而且,如果我必须重新编写代码或 DB 架构(尤其是在实时生产系统上),那么重新安装所花费的成本将轻松超过购买小 50% 的磁盘所带来的“节省”。

要真正理解这个问题,您必须真正了解 ASCII、Unicode 和 Unicode 的典型编码(如 UCS-2 和 UTF-8)。

于 2012-08-29T03:29:38.900 回答
1

我不是这方面的专家。但是为什么你不能使用 UTF-8 来获得小空间和 unicode 的组合呢?

于 2008-11-23T05:49:02.313 回答
1

我见过一些数据库,其中索引(索引?...不同的辩论)比数据大。如果可以摆脱索引中一半的存储需求(varchar),那么可以假设这等于给定页面的命中密度的两倍和更有效的填充因子,从而导致更快的数据检索/写入/锁定和更少的存储需求(已经提到过)。

于 2011-03-08T15:09:36.957 回答