Unicode 对存储和性能的影响

SQL Server 使用 UCS-2 编码方案存储 Unicode 数据。在这一机制下,所有 Unicode 字符均用 2 个字节存储。

Unicode 与非 Unicode 在存储字符数据上的差别取决于非 Unicode 数据是否使用双字节字符集存储。所有非东亚语言和泰语均用单字节存储非 Unicode 字符。因此,Unicode 存储这些语言所用的空间是指定非 Unicode 代码页所用空间的两倍。另一方面,许多其他亚洲语言的非 Unicode 代码页用双字节字符集 (DBCS) 指定字符存储。因此,对于这些语言,用非 Unicode 和 Unicode 存储几乎没有什么区别。

下表显示了用双字节字符集指定字符数据存储的非 Unicode 代码页。

语言

代码页

简体中文

936

繁体中文

950

日语

932

朝鲜语

949

Unicode 数据对性能的影响由于多种因素而复杂化,这些因素包括:

  • Unicode 排序规则和非 Unicode 排序规则之间的差别

  • 排序双字节和单字节字符之间的差别

  • 客户端与服务器之间的代码页转换

SQL Server 使用 Unicode 排序规则来执行用 Windows 排序规则定义的非 Unicode 数据的字符串比较。由于这些规则比非 Unicode 排序规则复杂得多,所以它们更占用资源。因此,尽管 Unicode 排序规则的代价通常更大,但 Unicode 数据与 Windows 排序规则定义的非 Unicode 数据之间的性能差别通常却很小。

SQL Server 使用非 Unicode 排序规则的唯一情况是对于使用 SQL 排序规则定义的非 Unicode 数据。在这种情况下,排序和扫描通常比应用 Unicode 排序规则时快。Unicode 排序规则应用于使用 Windows 排序规则或 SQL 排序规则定义的所有 Unicode 数据。

其次,由于 Unicode 数据是用双字节存储的,所以对大量 Unicode 数据排序可能比对非 Unicode 数据排序慢。另一方面,对亚洲 Unicode 字符排序比对特定代码页中的亚洲 DBCS 数据排序快,因为 DBCS 数据实际上是单字节和双字节宽度的混合,而 Unicode 字符具有固定的宽度。

其他性能问题主要取决于如何在 SQL Server 实例和客户端之间转化编码机制。通常,客户端/服务器代码页转换对性能的影响是微乎其微的。然而,您应该理解这一层上发生的事情。

ODBC API 3.6 或更低版本以及 DB-Library API 都不能识别 Unicode。对于使用由这些 API 定义的数据访问方法的客户端,资源被用于隐式地将 Unicode 数据转换为客户端代码页。另外,当客户端代码页不能识别某些 Unicode 字符时,客户端面临着数据被损坏的风险。

从 SQL Server 7.0 附带的 Microsoft 数据访问组件 2.7 开始,以后的 ODBC 版本以及 OLE DB 和 ADO 均能识别 Unicode 并采用 UCS-2 编码机制。因此,如果应用程序支持 Unicode,即使确实需要使用来自 SQL Server 实例的 Unicode 数据,也不存在转换问题。如果客户端使用支持 Unicode 的 API,但 SQL Server 实例中的数据存储机制不是 Unicode,也不存在转换问题。但是,如果任何字符的码位无法映射到 SQL Server 代码页,就面临数据插入或更新操作失败的风险。

Unicode 最佳实践

确定是否用 Unicode 存储非 DBCS 数据时,通常需要了解它对存储的影响,以及在客户端与数据交互时发生排序、转换和数据损坏的可能性有多大。排序和转换可能会影响性能,这取决于在哪里发生。但对大多数应用程序来说,对性能的影响微乎其微。索引设计合理的数据库更不可能受到影响。但是,数据损坏不仅影响应用程序和数据库的完整性,还会影响整个业务。考虑到这一因素,如果同时满足下列两个条件,将字符数据存储在特定的代码页中可能更合适:

  • 由于硬件限制,无法保留存储空间。或者,您在对大量数据执行频繁的排序,而且测试结果表明 Unicode 存储机制严重影响性能。

  • 您确定访问这些数据的所有客户端的代码页都与您的代码页相匹配,而且这一情况不会发生意外的变化。

大多数情况下,用 Unicode 存储字符数据(甚至是非 DBCS 数据)的决定应该更多地基于业务需要而非性能。当前,Internet 通信流量的快速增长促进了全球经济的发展,支持运行不同区域设置的客户端计算机正在变得比以往任何时候都重要。此外,选择一种能够支持世界各国用户需要的所有字符的代码页也变得越来越困难。