在SQL Server 2005中,将所有字符字段设置为nvarchar(MAX)而不是显式指定长度(例如nvarchar(255))有什么缺点吗?(除了不能在数据库级别限制字段长度之外)


当前回答

我发现的唯一问题是我们在SQL Server 2005上开发应用程序,在一个实例中,我们必须支持SQL Server 2000。我刚刚知道,SQL Server 2000不喜欢varchar或nvarchar的MAX选项。

其他回答

我发现的唯一问题是我们在SQL Server 2005上开发应用程序,在一个实例中,我们必须支持SQL Server 2000。我刚刚知道,SQL Server 2000不喜欢varchar或nvarchar的MAX选项。

根据已接受的答案中提供的链接,似乎是:

存储在nvarchar(MAX)字段中的100个字符将与存储在nvarchar(100)字段中的100个字符没有区别-数据将内联存储,并且您不会有“行外”读取和写入数据的开销。所以不用担心。 如果大小大于4000,数据将自动“行外”存储,这是你想要的。所以也不用担心。

然而……

不能在nvarchar(MAX)列上创建索引。可以使用全文索引,但不能在列上创建索引以提高查询性能。对我来说,这就决定了……总是使用nvarchar(MAX)是一个明显的缺点。

结论:

如果你想要一种贯穿整个数据库的“通用字符串长度”,它可以被索引,并且不会浪费空间和访问时间,那么你可以使用nvarchar(4000)。

1)当处理nvarchar(max) vs nvarchar(n)时,SQL服务器将不得不利用更多的资源(分配的内存和cpu时间),其中n是一个特定于字段的数字。

2)就绩效而言,这意味着什么?

在SQL Server 2005上,我从一个有15个nvarchar(max)列的表中查询了13000行数据。 我重复计时查询,然后将列更改为nvarchar(255)或更小。

优化之前的查询平均为2.0858秒。更改后的查询平均返回时间为1.90秒。这比基本select *查询提高了约184毫秒。这一数字提高了8.8%。

3)我的结果与其他几篇文章一致,表明存在性能差异。根据数据库和查询的不同,改进的百分比可能有所不同。如果您没有很多并发用户或很多记录,那么性能差异对您来说不是问题。但是,随着记录和并发用户的增加,性能差异也会增加。

截至SQL Server 2019, NVARCHAR(MAX)仍然不支持SCSU“Unicode压缩”-即使使用行内数据存储存储。SCSU是在SQL Server 2008中添加的,适用于任何ROW/ page压缩的表和索引。

因此,即使没有存储在LOB中,具有相同文本内容的NVARCHAR(1..4000)字段所占用的物理磁盘空间也是NVARCHAR(1..4000)字段的两倍。非scsu浪费取决于所表示的数据和语言。

Unicode压缩实现:

SQL Server使用Unicode标准压缩方案(SCSU)算法的实现来压缩存储在行或页压缩对象中的Unicode值。对于这些压缩对象,对nchar(n)和nvarchar(n)列的Unicode压缩是自动的[并且从未对nvarchar(max)使用]。

另一方面,PAGE压缩(自2014年以来)仍然适用于NVARCHAR(MAX)列,如果它们被写入行内数据。所以缺乏SCSU感觉就像“缺少优化”。与SCSU不同,基于共享前导前缀(例如。重复的值)。

然而,使用NVARCHAR(MAX)可能仍然“更快”,即使使用OPENJSON这样的函数会有更高的IO成本,因为它避免了隐式转换。这是一种隐式转换开销,它取决于使用的相对成本,以及字段是在过滤之前还是过滤之后被处理的。在VARCHAR(MAX)列中使用2019年的UTF-8排序规则时也存在同样的转换问题。

使用NVARCHAR(1-4000)也需要N*2个字节的~8000字节行配额,而NVARCHAR(MAX)只需要24个字节。总体设计和使用需要一起考虑,以考虑具体的实现细节。

+在我的数据库/数据/模式中,通过使用两列(读时合并),可以减少40%的磁盘空间使用,同时仍然支持溢出的文本值。SCSU虽然存在缺陷,但它是一种非常聪明且未得到充分利用的存储Unicode的更有效空间的方法。

一个问题是,如果你必须使用多个版本的SQL Server, MAX并不总是有效的。因此,如果您正在使用遗留DB或涉及多个版本的任何其他情况,您最好非常小心。