将整个DB字符集设置为Unicode与Oracle DB中的某些NVARCHAR2相比的缺点?

Joh*_*oth 6 database oracle unicode database-design oracle11g

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

我想我有以下两种选择:

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

我倾向于第二个选项(为了不必更改我已经存在的VARCHAR2脚本).

我的问题是:与第一种方案相比,第二种方案有哪些缺点和优点?性能较差吗?

Jus*_*ave 8

我强烈倾向于改变数据库的字符集.

这样做有潜在的缺点

  • 如果要在其他列中存储不在7位ASCII字符集中的数据,则会增加存储数据所需的空间量.假设您现有的字符集是允许存储英语和其他一些语言的8位字符集之一,则数据中的任何非英语字符通常每个字符需要2个或更多字节的存储空间.例如,如果要存储字符"h",那么这是一个英文字符,它是7位ASCII字符集的一部分,因此在单字节字符集或Unicode字符集中需要1个字节.另一方面,如果要存储字符"À",那么这不是英文而不是7位ASCII字符集的一部分,因此在Unicode字符集中需要2个字节的存储空间而在现有字符集中需要1个字节单字节字符集.其他字符需要3个字节的存储空间.
  • 声明a时,你必须关心字符与字节语义VARCHAR2.默认情况下,VARCHAR2(50)分配50个字节的存储空间,如果您使用的是AL32UTF8字符集而不是简单的1:1映射,则可以存储16到50个字符,就像使用单字节字符一样组.那将需要您增加列的大小(即三倍它们),以确保它们存储字符的适当数量或您在声明列(即指定字符长度语义VARCHAR2(50 CHAR)),或者您设置NLS_LENGTH_SEMANTICSCHAR前创建对象以将默认值更改为字符长度语义.在Oracle全球化论坛上讨论了在实例级别更改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列来获取此多语言数据.