6

我的表的某些列需要支持 Unicode 字符(假设是我所有列的 1%)。

我想我有以下两个选择:

  1. 将 Unicode 列实现为NVARCHAR2;或者
  2. 将整个数据库的字符集更改为支持 Unicode 的字符集(这样我可以使用VARCHAR2)。

我倾向于第二种选择(为了不必更改我已经存在的 VARCHAR2 脚本)。

我的问题是:与第一个选项相比,第二个选项的缺点和优点是什么?它的性能更低吗?

4

1 回答 1

8

我强烈倾向于更改数据库的字符集。

这样做有潜在的弊端

  • 如果您在其他列中存储的数据不是 7 位 ASCII 字符集,您将增加存储数据所需的空间量。假设您现有的字符集是允许您存储英语和其他几种语言的 8 位字符集之一,那么数据中的任何非英语字符通常每个字符需要 2 个或更多字节的存储空间。例如,如果您要存储字符“h”,这是一个英文字符,它是 7 位 ASCII 字符集的一部分,因此在单字节字符集或 Unicode 字符集中需要 1 个字节。另一方面,如果要存储字符“À”,则它不是英文,也不属于 7 位 ASCII 字符集,因此它需要 2 个字节的 Unicode 字符集存储空间,而 现有单字节字符集中的 1 个字节。其他字符将需要 3 个字节的存储空间。
  • 当你声明一个VARCHAR2. 默认情况下,VARCHAR2(50)分配 50 个字节的存储空间,如果您使用的是 AL32UTF8 字符集,则可以存储 16 到 50 个字符,而不是像使用单字节字符时那样进行简单的 1:1 映射放。这将需要您增加列的大小(即三倍)以确保它们存储适当数量的字符,或者您在声明列时指定字符长度语义(即VARCHAR2(50 CHAR))或您将您设置NLS_LENGTH_SEMANTICSCHAR之前创建对象以将默认值更改为字符长度语义。甲骨文全球化论坛上有讨论是否适合在实例级别更改 NLS_LENGTH_SEMANTICS -- Oracle 的顶级全球化专家之一 Sergiusz Wolicki 强烈反对它,尽管我个人更愿意在适当的情况下考虑它。您还可以NLS_LENGTH_SEMANTICS在会话级别设置,这是 Sergiusz 不反对但确实要求您在每次运行脚本时都这样做,这可能是一个问题。
  • 大多数工具不能很好地处理针对使用字符语义创建列的数据字典的查询。他们没有正确使用CHAR_LENGTHDATA_LENGTH列,他们想要字符长度与字节长度。如果您有现有的工具/脚本/等对数据字典运行查询以生成 DDL 或确定需要分配多少内存或您最终会遇到的其他情况,这对您来说可能是一个小问题或一个严重的痛苦得到时髦的结果。

但是,为所有数据使用单一字符集的优势远远超过了这些缺点

  • 处理NVARCHAR2列通常需要更改应用程序代码。由于您将同时拥有VARCHAR2NVARCHAR2列,因此这些代码更改和配置设置可能很重要,并且通常是一个主要的烦恼。不可避免地,您会发现在某些应用程序中错误地映射了特定列,并且您会遇到难以追踪的数据损坏错误。数据库和应用程序之间的抽象层越多,这一点就越真实。
  • 如果今天有 1% 的列需要支持 Unicode,那么明天必然会有更多的列需要支持 Unicode。随着附加要求的增加,将列的数据类型从VARCHAR2更改为NVARCHAR2是一件痛苦的事情——您需要添加一个新列,复制数据,删除旧列,重命名新列,并处理导致的行迁移。然后,您必须对所有现有应用程序进行更改,以便它们正确映射列。当企业决定再增加一列以支持其他语言并且您的数据库和应用程序已经支持 Unicode 时,这种努力和测试水平似乎相当过分。
  • SQL 语句必须以数据库字符集编码。如果您想NVARCHAR2在应用程序中将列中的数据用作 SQL 语句中的文字(例如,避免绑定变量窥视或更好地利用直方图)或在需要时作为生产支持的一部分,这往往会产生问题跟踪数据中的问题。
  • Unicode 字符集是 Oracle 强烈鼓励的方向,强烈反对使用NVARCHAR2列。这可能不会立即产生实际后果,但如果您的系统应该存在多年,那么将来很可能会产生后果。

Sergiusz 在此线程中很好地总结了 Oracle 的建议

甲骨文的建议:

  • 对于任何新数据库,使用 AL32UTF8 字符集创建它并忘记 NCHAR 数据类型。
  • 对于要制作多语言的任何现有应用程序,请将后端数据库迁移到 AL32UTF8 并忘记 NCHAR 数据类型。
  • 对于为大型遗留应用程序系统提供服务的任何现有非 Unicode 数据库,成本太高或无法迁移到 Unicode,您被要求添加一个必须支持多语言数据的次要模块,并且单独的数据库没有多大意义,对于这种多语言数据,您可以考虑使用 NVARCHAR2 列。
于 2012-10-09T13:52:03.767 回答