SQL Server中的varchar和nvarchar数据类型的主要性能差异是什么?

248

我正在使用 SQL Server 2005 开发学校的小型Web应用程序的数据库。
在使用 varcharnvarchar 的问题上,我看到了几种不同的观点:

  1. 如果你没有处理大量国际化数据,那就使用 varchar,否则使用 nvarchar
  2. 对于所有内容都使用 nvarchar

我开始看到第二个观点的优点。我知道 nvarchar 占用的空间是 varchar 的两倍,但考虑到这只会为几百名学生存储数据,这并不是一个很大的问题。对我来说,似乎最容易的方法是不用担心它,让所有内容都使用 nvarchar。还是有什么我没注意到的吗?


类似的问题在这里:https://dev59.com/xXVC5IYBdhLWcg3wYQAp。有趣的是,它得出了完全相反的结论。 - Booji Boy
6
参考更广泛的讨论串,该串得出了相反的结论。https://dev59.com/xXVC5IYBdhLWcg3wYQAp - dkretz
3
Jason:我希望这不是一个不恰当的要求,但是你能否考虑将已接受的答案更改为 gbn's。JoeBarone的答案有许多严重错误,如果它被“接受”,会误导新手做出错误的选择。无需“总是使用NVARCHAR”,这样做可能对性能和硬件成本/预算产生非常负面的影响。少数行,甚至几千行都没有关系,但系统增长速度比人们预期的更快,所以目前接受的答案是对社区的不利影响。谢谢。 - Solomon Rutzky
14个回答

4
我经常在工作中处理这个问题:
  • 库存和定价的FTP数据源 - 商品描述和其他文本使用nvarchar时,使用varchar就足够了。将它们转换为varchar可以将文件大小减少近一半,并且有助于上传。

  • 上述情况一直很好,直到有人在商品描述中添加了特殊字符(可能是商标,记不清了)

我仍然不会每次都使用nvarchar而不是varchar。如果存在任何疑虑或可能出现特殊字符的情况,我会使用nvarchar。我发现当我对填充字段拥有100%的控制权时,我主要使用varchar。


3
在这场讨论中,为什么没有提到UTF-8呢?能够存储完整的Unicode字符范围并不意味着必须始终分配每个字符两个字节(或使用UNICODE术语中的“代码点”)。所有ASCII字符都是UTF-8编码的。SQL Server是否检查VARCHAR()字段的文本是否是严格的ASCII(即最高字节位为零)?我希望不是这样。
如果您想存储Unicode并希望与旧的ASCII应用程序兼容,则可以考虑使用VARCHAR()和UTF-8:只有在需要时才会使用更多空间。
对于那些不熟悉UTF-8的人,我建议看一下这篇入门文章

2
你所建议的方法可能适用于某些应用程序,但也必须考虑到额外编码层对SQL文本处理方式的影响。特别是,排序规则、搜索和模式匹配将受到影响。如果针对数据库运行报告,则标准报告工具将无法正确解释多字节字符。批量导入和导出也可能受到影响。我认为,从长远来看,这种方案可能会带来更多麻烦,不值得一试。 - Jeffrey L Whitledge
1
无法在VARCHAR列中存储UTF-8。 MSSQL将始终将您的UTF-8数据转换为列排序规则。 如果您弄乱了排序规则(例如尝试将CP1252存储在Latin_1中),则转换将无法正常工作,并且您的数据中会出现额外的字节。 当您将latin_1转换为UTF-8(在应用程序端)并再次转换为latin_1(db端)时,它可能看起来运行良好,但这只是一种幻觉。 您可以通过使用freetds并将协议设置为小于7的某些内容来绕过DB自动转换为列排序规则,但您将失去查询nvarchar的能力。 - chugadie
1
@chugadie和Tevya:这个答案有点不合逻辑。SQL Server只使用UCS-2/UTF-16来存储Unicode数据(即XML和带有“N”前缀的类型)。您不能选择使用UTF-8。此外,Unicode编码(UTF-8、UCS-2/UTF-16和UTF-32)不能应用于VARCHAR字段。 - Solomon Rutzky

2

有些特殊情况下,您需要故意限制数据类型以确保其中 不会 包含来自某个字符集的字符。例如,我曾经遇到这样的情况:我需要将域名存储在数据库中。当时,域名国际化不是很可靠,因此更好地在基本层面上限制输入,以避免任何潜在问题。


1
如果您只是因为某个系统存储过程要求使用 NVARCHAR,最常见的情况是不可解释的 sp_executesql,并且您的动态 SQL 非常长,从性能角度考虑,您最好在 VARCHAR 中执行所有字符串操作(连接、替换等),然后将最终结果转换为 NVARCHAR 并将其提供给过程参数。因此,不要总是使用 NVARCHAR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接