NVARCHAR使用的大小是否重要?
在使用NVARCHAR时,大小确实会影响性能。查询优化器会查看元数据来规划查询。它根据提供的长度估计行大小,这可能导致性能问题。例如,当您需要对一个varchar(10)列进行排序时,可能计划在RAM上运行排序操作,但对于varchar(1000)的相同查询可能计划在辅助存储上运行。
我尝试使用领域知识来估计所需的大小。此外,您可能需要为将来的维护留出一些空间。例如,如果您认为您的数据可能最多有50个字符,那么请使用varchar(70)而不是50,以便它可以处理应用程序使用情况中的不可预测的未来更改。
我从这篇博客文章中了解到这一点(我不是作者):http://aboutsqlserver.com/2010/08/18/what-is-the-optimal-size-for-variable-width-columns/
注意:不要盲目选择较小的长度。更改字段大小可能会带来很大的维护工作。我记得当我为LastName字段选择了一个较小的长度时,一些用户无法在系统中注册。我们不得不更新一个正在使用的关键数据库(增加字段长度需要时间),并编译程序并重新部署。如果我选择了适当的字段大小,我可以避免所有这些麻烦。
您可能还想阅读一下nvarchar(max)和nvarchar(n)之间的区别,其中n>4000对于4000来说,该字段基本上与nvarchar(max)相似。(Are there any disadvantages to always using nvarchar(MAX)?)
数据库中使用NVARCHAR的大小是否重要?原因是为了防止错误的数据进入数据库。如果你喜欢电话号码上写着“如果你想得到真实的答案,请打给胖秘书而不是可爱的秘书。”(这是我在一个实际的客户文件中找到的不太随机的例子),那倒无所谓。用户很快就会发现哪些字段足够大,以至于可以用来存储注释,这往往会使字段中的数据变得无用。
至于NVARCHAR(MAX),除非你希望有超过4000个字符,否则使用它是一个坏主意。查找索引和VARCHAR(MAX)以了解原因。
另一方面,在大多数情况下,我认为这只是“最后的理智检查”。也就是说,对于电话号码,我可能会使用VARCHAR(20)
(我喜欢取10、20、100、200的整数)来考虑不同的区域/国家代码、分机号码等。通常应该有额外的数据验证约束(数据库、数据访问层或其他方式),以确保数据符合任何业务规则。
在MSDN文档中,我们可以得知NVARCHAR的存储大小与实际输入数据的长度有关。存储大小等于实际数据长度的两倍加上2个字节。这个长度参数的存在可以用来约束数据的长度,以防止出现过长的文本。另外,如果有其他原因需要对数据进行约束,比如业务规则或者系统其他部分的约束,为了保持整个系统的数据完整性,也可以添加约束。
需要注意的是,NVARCHAR(MAX)的存储方式与NVARCHAR(X)不同,不能简单地用NVARCHAR(MAX)替代NVARCHAR(X)。存储空间是相同的,但是NVARCHAR(MAX)的存储方式更像是一个BLOB而不是内联字段。
在测试中,发现在NVARCHAR的大小达到4000之后,其行为会发生变化。文档中并没有明确说明当声明大小为4001或更大时会发生什么。
文档中的措辞已经有所更改,现在的表述是“存储大小是两倍n字节加上2个字节”,这与之前的回答有所矛盾。希望这只是文档错误或误导,有人能够确认一下吗?
根据使用SQL Server 2016进行测试,通过DATALENGTH()函数获取字段的长度,可以发现在Unicode范围0-65,535内,NVARCHAR(Y)返回的长度是n个字符的2n个字节。而使用NCHAR(Y)则返回的长度是n个字符的2y个字节。不清楚+2个字节的去向,我猜测DATALENGTH()函数返回的是字段本身的数据,而+2个字节可能是SQL Server必须存储在某个地方的指针。
根据上述内容,我们可以总结出以下问题的出现原因和解决方法:
问题的出现原因:
- 存储大小与实际输入数据的长度有关,但文档中并没有明确说明为什么要加上2个字节的存储大小。
问题的解决方法:
- 如果需要对数据长度进行约束,可以使用长度参数进行限制。
- 如果有其他原因需要对数据进行约束或保持数据完整性,可以添加相应的约束。
- 需要注意NVARCHAR(MAX)和NVARCHAR(X)的存储方式不同,不能简单地替换使用。
- 如果NVARCHAR的大小超过4000,其行为会发生变化,需要注意。
- 对于文档中的表述变化,希望这只是文档错误或误导,需要确认。