根据Micorosoft Docs对 nvarchar 长度参数的定义

nvarchar [ ( n | max ) ]

Variable-size string data. n defines the string size in byte-pairs and can be a value from 1 through 4,000. max indicates that the maximum storage size is 2^30-1 characters (2 GB). The storage size is two times n bytes + 2 bytes. 

可知,n的取值范围在1 - 4,000,如果超过此长度,可使用max,最大支持2GB的数据存储。

 

通常来说,如果实际存入nvarchar(max)的数据小于8000字节(4000个双字节字符),那么SQL Server在实际存储时会将其视作普通的varchar类型(存储空间占用为字符串实际长度+2字节)。

虽说存储空间占用一致,但是在查询时的内存消耗却是不一样的。 这是因为在做数据查询的时候,是使用声明的大小分配内存的,这将导致大量内存的浪费。

当加载数据到内存时,varchar和nvarchar列被假定为半满长度。 varchar(2000)列将导致每行1000个字节的内存请求,而nvarchar(2000)将导致每行2000个字节的请求。

以下来源sqlservercentral中一个帖子中的实验:

  谨慎在SQL Server中使用nvarchar(max)_SQL Server

 (NULL代表内存请求小于5M)

 

发帖人使用同一批数据(字段长度小于60字节且95%的数据小于等于37字节)插入不同类型的列中,进行查询时的内存消耗分析,发现nvarchar(max)的内存使用率仅有2%。

这是因为在查询时,必须将数据加载到内存中。数据存放在磁盘中时可以根据数据的实际长度存放,但是查询时内存声明必须在数据到达之前进行--直到数据读入内存中时,才知道数据实际的宽度,那时则为时已晚。

所以在实际使用时,varchar/nvarchar的长度参数还是应该根据字段实际长度进行设置,以减少不必要的内存占用。

附:关于nchar 或 nvarchar的使用建议:

  • 如果列数据项的大小一致,则使用 nchar。
  • 如果列数据项的大小差异相当大,则使用 nvarchar。
  • 如果列数据项大小相差很大,而且字符串长度可能超过 4,000 双字节字符,请使用 nvarchar(max)。