AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 218479
Accepted
gotqn
gotqn
Asked: 2018-09-25 22:52:26 +0800 CST2018-09-25 22:52:26 +0800 CST 2018-09-25 22:52:26 +0800 CST

`nvarchar/nchar` 何时与 SQL Server 2019 一起使用?

  • 772

微软在 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 吗?

sql-server datatypes
  • 2 2 个回答
  • 2617 Views

2 个回答

  • Voted
  1. Paul White
    2018-09-27T23:00:14+08:002018-09-27T23:00:14+08:00

    UTF-8 支持为您提供了一组新选项。潜在的空间节省(没有行或页面压缩)是一个考虑因素,但类型和编码的选择应该主要根据比较、排序、数据导入和导出的实际需求来进行。

    您可能需要进行的更改比您想象的要多,因为例如一个nchar(1)类型提供了两个字节的存储空间。这足以在BMP中存储任何字符(代码点 000000 到 00FFFF)。该范围内的某些字符在 UTF-8 中仅使用 1 个字节进行编码,而其他字符则需要 2 甚至 3 个字节(有关更多详细信息,请参阅此比较表)。因此,确保在 UTF-8 中覆盖同一组字符需要char(3).

    例如:

    DECLARE @T AS table 
    (
        n integer PRIMARY KEY,
        UTF16 nchar(1) COLLATE Latin1_General_CI_AS,
        UTF8 char(1) COLLATE Latin1_General_100_CI_AS_SC_UTF8
    );
    
    INSERT @T (n, UTF16, UTF8)
    SELECT 911, NCHAR(911), NCHAR(911);
    

    给出了熟悉的错误:

    消息 8152、级别 16、状态 30、行 xxx
    字符串或二进制数据将被截断。

    或者,如果跟踪标志 460 处于活动状态:

    消息 2628,级别 16,状态 1,行 xxx
    字符串或二进制数据将在表 '@T' 列 'UTF8' 中被截断。截断值:“”。

    将 UTF8 列扩展为char(2)或varchar(2)解决以下错误NCHAR(911):

    DECLARE @T AS table 
    (
        n integer PRIMARY KEY,
        UTF16 nchar(1) COLLATE Latin1_General_CI_AS,
        UTF8 varchar(2) COLLATE Latin1_General_100_CI_AS_SC_UTF8
    );
    
    INSERT @T (n, UTF16, UTF8)
    SELECT 911, NCHAR(911), NCHAR(911);
    

    但是,如果它是 eg NCHAR(8364),则需要将列进一步扩展为char(3)或varchar(3)。

    另请注意,UTF-8 排序规则都使用补充字符,因此不适用于复制。

    除此之外,UTF-8 支持目前仅处于预览阶段,因此无法用于生产用途。

    • 13
  2. Best Answer
    Solomon Rutzky
    2018-10-03T11:50:38+08:002018-10-03T11:50:38+08:00

    这可以减少表和索引的大小(强调添加)

    仅当大多数字符本质上是[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 编码的 char 数据类型

    确实。事实上,在大多数情况下,我并没有找到一个令人信服的理由来使用它。真正受益于 UTF-8 的唯一场景是:

    1. 数据主要是标准 ASCII(值 0 - 127)
    2. 它需要是 Unicode,因为它可能需要存储比任何单个 8 位代码页上可用的字符范围更广的字符(即VARCHAR)
    3. 大多数数据都存储在行外(因此页面压缩甚至不起作用)
    4. 您有足够的数据需要/想要减少非查询性能原因的大小(例如减少备份大小,减少备份/恢复所需的时间等)
    5. 您不能使用聚集列存储索引(在这种情况下,表的使用可能会使性能变差?)

    我的测试表明,在几乎所有情况下,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 支持:救世主还是假先知?

    • 7

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve