我有一个很少使用的“评论”类型的列——在 300 万条记录中大约有 6% 是非空的。平均长度(使用时)为 6 个字符,目前最大约为 3KB。此字段最多 4000 个字符是合理的。我有两个选择:
comments varchar(max) NULL -- this is the current column definition
comments varchar(4000) SPARSE NULL
我目前的理解是,在这两种情况下,一个NULL
值都不需要存储——只需要列的位集和行元数据中NULL
的长度。0
但是对于非空情况,一个比另一个有明显的优势吗?
带有值的稀疏列的额外 4 字节指针表明它们始终存储在行外text
或非常大的varchar(max)
字段中。是这样吗?
如果是这样,我倾向于使用varchar(max)
,因为如果总行长度超过 8KB,它只会在行外存储值,并且我的大多数值都很短,不太可能超过限制。
我还没有看到 BOL 中解决了这种特殊情况,所以我希望这里有人对 MSSQL 的内部有足够的了解,可以提供一些见解。
(如果重要的话,我目前正在使用 2008R2,但希望尽快升级到 2014。)
使用 时,非 NULL情况没有任何优势,
SPARSE
事实上,有两个缺点:正如您几乎已经收集到的那样,该
SPARSE
选项仅对固定长度的数据类型有意义;我想不出将它用于可变长度类型的单一理由。我不确定额外的 4 个字节是否意味着它被存储在行外,并且当
MAX
类型超过 8000 字节时,它们并不完全是行外的,因为行中有 16 字节指针指向该行-行位置。坚持
VARCHAR(4000)
, noSPARSE
,我什至会考虑制作它NOT NULL DEFAULT('')
(空字符串仍然是 0 字节,但现在你不需要弄乱 NULL 指示符,并且评论真的可以是“未知”而不是“无评论”吗“?)。我第二 Srutzky。同意。
现在,让我补充一点与您的决定有很大关系的运营观点。由于您目前使用 varchar(max) 显然对您来说没有问题,但摆脱它在性能和操作能力方面具有一定的优势。
举个例子,有一个有用的功能叫做 Online Index Rebuild,它是企业版独有的功能。
请允许我稍微偏离正题;长期使用后,索引变得碎片化,需要重建。但是,通常的构建会导致对基础表的严重锁定,并且在重建索引时,索引不可用,这使得查询在非常大的数据库上死气沉沉。这不仅仅是“嗯……有点慢”,而是“2 秒查询需要 25 分钟!” 一种紧急情况。因此,在 24/7 系统中,这不是一种选择。这就是在线索引重建发挥作用的地方;如果您支付 25,000 美元左右获得使用企业版特权的核心许可,您可以在 24/7 系统上神奇地重建索引,而不会影响用户。
除非,如果某些开发人员投入 varchar(max) 它将无法工作。然而,它很乐意在 varchar(4000) 上。如果数据包含超过 8000 个字符,您将卡在 varchar(max) 中,无法进行在线重建,这将是上级肯定会注意到的操作问题。
..这只是一个例子。因此,我的建议是与您组织中的生产 DBA 交谈,并询问他们喜欢和不喜欢什么。由于您当前正在运行 varchar(max) 我认为这不是问题,但您可以通过删除它来应对未来的挑战。虽然,如果表用于不经常访问的存储而无需在线索引重建,那么使用 varchar(max) 会非常好。这是只有您的生产 DBA 才能进行的调用。
如果您在没有专门 DBA 的较小商店,请提供有关表的使用和操作要求的更多详细信息(是否 24/7 有五个九的要求?是否集群?您的服务窗口多长时间?当前版本和未来的版本更改计划?),社区可以为您提供更好的建议。我可能会询问太多信息,但这是有经验的 DBA 依靠的那种细节来做出正确的决定。