SQL Server 的良好实践:nvarchar(max) 的性能表现

20

我是一位新的 .net 程序员。作为一个新手,我总是尽可能地遵循最佳实践。今天我开始学习 SQL Server,并询问同事用户描述列应该使用哪种数据类型。他告诉我使用 nvarchar(MAX),我按照他说的做了,并且效果很好。

但是,我们在这种情况下是否总是应该使用 nvarchar(max)?还是更好地分配类似 500 个字符的长度?

我提出这个问题是因为我谷歌了一下,看到有人说 nvarchar(max) 会为列保留大量内存,这可能会降低数据库的性能。

编辑:太棒了,你们的回答让我对这个话题非常清楚了。没有 Unicode 方面的问题,因此我将选择 varchar(600)。


一个描述可以超过4,000个字符吗?UI可以显示多少内容或者有最大长度的限制吗?您想允许高达2GB的条目吗? - Martin Smith
如果你确实需要超过4000个Unicode字符,那么请使用nvarchar(max) - 这就是它存在的目的。但是,如果你从经验上知道某列最多只有25或50个字符(例如电话号码),或者255个字符(电子邮件列),那么不要使用nvarchar(max) - 使用适当的数据类型,在这种情况下应该使用nvarchar(25)或适合你情况的长度。需要知道你的数据将会是什么样子 - 根据此设计你的表格! - marc_s
nvarchar = Unicode - 每个字符占用2个字节,因此最大长度为 nvarchar(4000)varchar = 非 Unicode - 每个字符占用1个字节,因此最大长度为 varchar(8000) - marc_s
1
太棒了,各位大佬的回答让我对这个话题有了清晰的认识。没有Unicode的问题,因此我将使用varchar(600)。 - Koni
你会禁止使用Unicode吗?如果有人的工作档案包括⚕,该怎么办?那安贤洙、Виктор Ан、Ahn Hyun-soo这些人名呢?我很失望,因为我必须去健身房锻炼。显然,SO并不采取你的方法。 - Tom Blodget
显示剩余6条评论
3个回答

15

最佳实践是在设计表之前进行适当的数据分析。如果没有上下文,人们可能会认为一个描述不包含数页文字,因此"max"选项可能不合适。在选择varchar(max)时,还要考虑到另一个问题:通常需要提供支持来在应用程序中显示这些值。如果您不打算设计GUI来完成此操作,则该选择可能不合适。

还有一个注意事项——通过选择超出您预见需求的数据类型来未雨绸缪通常是徒劳无功的。


谢谢!在这种情况下,该字段将允许用户设置有关其工作资料的描述。我考虑最多600个字符。 - Koni
@MarianoGianni 是的。这些是编辑决策,而不是技术决策。您可能还想限制行数等内容。并且,就像 Stack Overflow 一样,在超出限制时提供适当的反馈和编辑功能。 - Tom Blodget
这并不是一个是否应该限制的问题,而是在哪里限制的问题。你想让数据库在达到一定大小限制后抛出异常吗?实际上,对于存储大型文本文档,我从来没有后悔过使用最大值。我已经多次后悔使用了小于最大值的限制。虽然不想打破YAGNI的幻想,但假装问题不存在并故意目光短浅并不是一个好的生活策略。 - Jeffrey Vest

13
除了不能使用LOB数据类型进行在线索引重建外,选择nvarchar(max)而不是nvarchar(4000)或nvarchar(1000)还会对性能造成影响。
SQL Server会假设平均值为最大大小的一半,这直接影响SQL Server为查询授予的内存。
Aaron Bertrand在此演示/转录中解释了这一点。
当SQL Server查看一个列并且你已经决定:“哦,我们只需将其设置为nvarchar 4000,以防万一。” SQL Server实际上认为平均值将包含2000个字符。因此,当你有varchar 4000并且它大得多且所有的值都是10个字符时,实际上SQL Server将授予这个查询的内存是每行2000字节,仅针对该列,而不是实际需要的10个字节。因此,你可以看到授予的KB随着时间的推移而急剧增加,以及如何影响经过的时间。
- GroupBy.org - T-SQL : Bad Habits and Best Practices - Aaron Bertrand

1
这里还有几个链接供您参考:http://rusanu.com/2010/03/22/performance-comparison-of-varcharmax-vs-varcharn/ 和 http://sqlblog.com/blogs/paul_white/archive/2012/08/31/deletes-that-split-pages-and-forwarded-ghosts.aspx。 - Martin Smith
@MartinSmith 已添加。谢谢! - SqlZim

5
每当您有一个可能包含国家字符(非简单ASCII)并且长度超过8,000字节的字段时,应使用 nvarchar(max)。在这种情况下,它是完全正确的选择。
如果只有简单的ASCII,则适用 varchar(),但 nvarchar() 不会产生太大影响。
如果您有一个已知最大长度或合理最大长度的字段,则不适用 max。因此,使用 stateName varchar(32)(或其他),而不是 stateName varchar(max)。或者,使用 productDescription nvarchar(255),而不是 productDescription nvarchar(max)
在描述很长的情况下,可以使用它。但不要过度使用。

8
限制是8000字节而不是字符。因此,带有双字节字符的4000个字符相当于8000字节。 - Martin Smith

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