微软在 SQL Server 2019 中引入了对数据类型的UTF-8 支持,CHAR
并表示:VARCHAR
此功能可能会显着节省存储空间,具体取决于使用的字符集。例如,使用启用 UTF-8 的排序规则将具有 ASCII 字符串的现有列数据类型从 NCHAR(10) 更改为 CHAR(10),可以将存储需求减少近 50%。这种减少是因为 NCHAR(10) 需要 22 个字节来存储,而 CHAR(10) 需要 12 个字节来存储相同的 Unicode 字符串。
UTF-8 似乎支持所有脚本,所以基本上我们可以开始将 Unicode 数据存储在varchar
和char
列中。正如文档中所说,这可以减少表和索引的大小,并且从那里我们可以获得更好的性能,因为读取的数据量更少。
我想知道这是否意味着我们可以停止使用实现 UTF-16 的列nvarchar
?nchar
任何人都可以指出一个场景和理由,不要使用带有UTF
编码的 char 数据类型并继续使用 n-chars 吗?
UTF-8 支持为您提供了一组新选项。潜在的空间节省(没有行或页面压缩)是一个考虑因素,但类型和编码的选择应该主要根据比较、排序、数据导入和导出的实际需求来进行。
您可能需要进行的更改比您想象的要多,因为例如一个
nchar(1)
类型提供了两个字节的存储空间。这足以在BMP中存储任何字符(代码点 000000 到 00FFFF)。该范围内的某些字符在 UTF-8 中仅使用 1 个字节进行编码,而其他字符则需要 2 甚至 3 个字节(有关更多详细信息,请参阅此比较表)。因此,确保在 UTF-8 中覆盖同一组字符需要char(3)
.例如:
给出了熟悉的错误:
或者,如果跟踪标志 460 处于活动状态:
将 UTF8 列扩展为
char(2)
或varchar(2)
解决以下错误NCHAR(911)
:但是,如果它是 eg
NCHAR(8364)
,则需要将列进一步扩展为char(3)
或varchar(3)
。另请注意,UTF-8 排序规则都使用补充字符,因此不适用于复制。
除此之外,UTF-8 支持目前仅处于预览阶段,因此无法用于生产用途。
仅当大多数字符本质上是
[space]
,0 - 9
,A - Z
,a - z
和一些基本标点符号时,才可能缩小大小。在该特定字符集之外(在实际使用中,标准 ASCII 值 32 - 126),您的大小最多等于NVARCHAR
/ UTF-16,或者在许多情况下更大。当心。UTF-8 并不是一个神奇的“修复一切”开关。在所有其他条件相同的情况下,是的,少读确实会提高性能。但这里的“所有其他事物”并不相等。即使仅存储标准 ASCII 字符(意思是:所有字符都是 1 字节,因此与存储相比需要一半的空间
NVARCHAR
),使用 UTF-8 也会有轻微的性能损失。我相信这个问题是由于 UTF-8 是一种可变长度编码,这意味着必须在读取每个字节时对其进行解释,以便知道它是一个完整的字符还是下一个字节是它的一部分。这意味着所有字符串操作都需要从头开始并逐字节进行。另一方面,NVARCHAR
/ UTF-16 始终是 2 字节(即使是补充字符也由两个 2 字节代码点组成),因此可以以 2 字节块读取所有内容。在我的测试中,即使只有标准的 ASCII 字符,将数据存储为 UTF-8 也不会节省经过的时间,但对于 CPU 时间来说肯定更糟。那是没有数据压缩,所以至少使用的磁盘空间更少。但是,当使用压缩时,UTF-8 所需的空间仅小 1% - 1.5%。因此,UTF-8 有效地节省了空间,但 CPU 时间更长。
使用时事情会变得更加复杂,
NVARCHAR(MAX)
因为 Unicode 压缩不适用于该数据类型,即使该值小到可以存储在行中。但是,如果数据足够小,它仍然应该受益于行或页面压缩(在这种情况下它实际上变得比 UTF-8 更快)。但是,行外数据不能使用任何压缩。尽管如此,使表成为聚集列存储索引确实大大减少了NVARCHAR(MAX)
(即使在使用聚集列存储索引时它仍然比 UTF-8 略大)。确实。事实上,在大多数情况下,我并没有找到一个令人信服的理由来使用它。真正受益于 UTF-8 的唯一场景是:
VARCHAR
)我的测试表明,在几乎所有情况下,NVARCHAR 都更快,尤其是当有更多数据时。事实上,21k 行,平均每行 5k 个字符,UTF-8 需要 165 MB,
NVARCHAR
未压缩需要 236 MB。然而NVARCHAR
,经过的时间快了 2 倍,CPU 时间至少快了 2 倍(有时更多)。尽管如此,它确实在磁盘上多占用了 71 MB。除此之外,我仍然不建议使用 UTF-8,至少从 CTP 2 开始,因为我在此功能中发现了各种错误。
有关此新功能的详细分析,包括对 UTF-16 和 UTF-8 之间差异的解释,以及这些错误的列表,请参阅我的帖子:
SQL Server 2019 中的原生 UTF-8 支持:救世主还是假先知?