在SQL Server 2005中,将所有字符字段设置为nvarchar(MAX)而不是显式指定长度(例如nvarchar(255))有什么缺点吗?(除了不能在数据库级别限制字段长度之外)
当前回答
一个缺点是,您将围绕一个不可预知的变量进行设计,您可能会忽略而不是利用内部SQL Server数据结构,逐步由Row(s)、Page(s)和Extent(s)组成。
这让我想到了C中的数据结构对齐,并且通常认为知道对齐是一件好事(TM)。相似的想法,不同的背景。
页面和区段的MSDN页面
行溢出数据的MSDN页面
其他回答
截至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的更有效空间的方法。
一个不使用max或文本字段的原因是,你不能执行在线索引重建,即REBUILD WITH online = ON,即使与SQL Server企业版。
我有一个udf填充字符串,并把输出varchar(max)。如果直接使用它,而不是将其转换回正在调整的列的适当大小,则性能非常差。我最终将udf设置为一个任意长度的大音符,而不是依赖udf的所有调用者将字符串重新转换为较小的大小。
一个问题是,如果你必须使用多个版本的SQL Server, MAX并不总是有效的。因此,如果您正在使用遗留DB或涉及多个版本的任何其他情况,您最好非常小心。
如上所述,这主要是存储和性能之间的权衡。至少在大多数情况下是这样。
然而,在选择n/varchar(Max)而不是n/varchar(n)时,至少还有一个其他因素需要考虑。数据是否将被索引(例如,一个姓氏)?因为MAX定义被认为是LOB,所以任何定义为MAX的东西都不能用于索引。如果没有索引,在WHERE子句中涉及数据作为谓词的任何查找都将被迫进行全表扫描,这是您可以获得的数据查找的最差性能。
推荐文章
- 比较两个SQL Server数据库(模式和数据)的最佳工具是什么?
- 在SQL中,如何在范围中“分组”?
- 选项(RECOMPILE)总是更快;为什么?
- 设置数据库从单用户模式到多用户
- oracle中的RANK()和DENSE_RANK()函数有什么区别?
- 我如何转义一个百分比符号在T-SQL?
- SQL Server恢复错误-拒绝访问
- 的类型不能用作索引中的键列
- SQL逻辑运算符优先级:And和Or
- 如何检查一个表是否存在于给定的模式中
- 添加一个复合主键
- 如何在SQL Server Management Studio中查看查询历史
- SQL Server索引命名约定
- 可以为公共表表达式创建嵌套WITH子句吗?
- 什么时候我需要在Oracle SQL中使用分号vs斜杠?