SQL Server 如何验证UTF-8列实际上保存了空间?

nlejzf6q  于 2023-02-07  发布在  其他
关注(0)|答案(2)|浏览(165)

SQL Server 2019引入了对广泛使用的UTF-8字符编码的支持。
我有一个很大的表来存储发送的电子邮件。所以我想给予这个功能。

ALTER TABLE dbo.EmailMessages 
ALTER COLUMN Body NVARCHAR(MAX) COLLATE Latin1_General_100_CI_AI_SC_UTF8;

ALTER TABLE dbo.EmailMessages  REBUILD;

我担心的是我不知道如何验证大小的增加,似乎流行的大小估计脚本在这种情况下不能正确地报告大小。

mjqavswn

mjqavswn1#

基本上,列类型必须转换为VARCHAR(MAX),然后以更紧凑的方式存储数据:
为限制上述方案所需的更改量,在现有数据类型CHAR和VARCHAR中启用了UTF-8。创建对象的归类或将其更改为带“_UTF8”后缀的归类时,字符串数据将自动编码为UTF-8,例如从LATIN1_GENERAL_100_CI_AS_SC更改为LATIN1_GENERAL_100_CI_AS_SC_UTF8。
可使用sp_spaceused检查尺寸:

sp_spaceused N'EmailMessages';

如果未使用的空间很大,则可能需要reorganize

ALTER INDEX ALL ON dbo.EmailMessages REORGANIZE WITH (LOB_COMPACTION = ON);

在我的情况下,大小减少了约2倍(主要是英语文本)。

vm0i2vca

vm0i2vca2#

正如其他人已经提到的,应该使用VARCHAR而不是NVARCHAR来存储UTF-8编码的文本。
您可以使用如下查询来比较字符串长度。它假定一个名为@Data的表具有一个名为StringNVARCHAR列。

SELECT *
FROM @Data
CROSS APPLY (
    SELECT
        CONVERT(VARCHAR(MAX), String COLLATE LATIN1_GENERAL_100_CI_AS_SC_UTF8) AS Utf8String
) U
CROSS APPLY (
    SELECT
        LEN(String) AS Length,
        --LEN(Utf8String) AS Utf8Length,
        DATALENGTH(String) AS NVarcharBytes,
        DATALENGTH(Utf8String) AS Utf8Bytes
) L
CROSS APPLY (
    SELECT
        CASE WHEN Utf8Bytes < NVarcharBytes THEN 'Yes' ELSE '' END AS IsShorter,
        CASE WHEN Utf8Bytes > NVarcharBytes THEN 'Yes' ELSE '' END AS IsLonger
) C
CROSS APPLY (
    SELECT
        CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), String), 1) AS NVarcharHex,
        CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), Utf8String), 1) AS Utf8Hex
) H

您可以将FROM @Data替换为类似FROM (SELECT Email AS String FROM YourTable) D的内容以查询特定数据。将SELECT *替换为SELECT SUM(NVarcharBytes) AS NVarcharBytes, SUM(Utf8Bytes) AS Utf8Bytes以获取总计。
参见this db<>fiddle
参见:UTF-8和UTF-16之间的存储差异。

相关问题