使用 MAX 文本或更具体的较小类型

Phr*_*cis 23 performance database-design sql-server datatypes varchar

有人正在审查我用于创建表的 DDL 代码并建议,当他们看到我看到使用VARCHAR(256)文本字段时,我希望它非常小,比如名字或其他什么,我应该总是只使用VARCHAR(MAX)和链接为什么使用 varchar(max )。我读过它,但它似乎过时了,因为它专注于 2005 年,并且似乎没有提供任何真正的理由来在所有文本字段上每行分配最多 2 GB。

从性能、存储等角度来看,应该如何决定是使用VARCHAR(MAX)SQL Server 的现代版本还是使用更小更具体的类型?(例如,2008、2012、2014)

Pau*_*ite 32

我应该总是(n)varchar(max)用于文本列吗?

不。

对于 SQL Server,max只有在别无选择时才应指定数据类型。相反,应该选择正确的基本类型(varcharnvarchar)并指定适合要存储的数据的明确最大长度。

无论列的类型为varchar(n)varchar(max),物理存储都是相同的,所以这不是问题。

(n)varchar(max)随处选择的原因围绕着功能、计划质量和性能。

详尽的列表可能不切实际,但除其他外,max列:

特征

  • 需要单独的约束来强制最大长度
  • 不能是索引中的键(因此也没有唯一约束)
  • 可能会阻止在线 DDL(包括索引重建和添加新的非空列)
  • 通常不支持“较新”的功能,例如列存储
  • 有关更具体的功能和限制,请参阅产品文档。一般模式是围绕max数据类型存在尴尬的限制和限制。并非所有限制和副作用都记录在案。

表现

  • 需要在执行引擎中进行特殊处理,以考虑可能非常大的尺寸。通常,这涉及使用效率较低的代码路径和流接口
  • 可能对外部代码(以及其他 SQL Server 组件,如 SSIS)产生类似的意外后果,这些代码还必须准备好处理高达 2GB 的数据
  • 在内存授权计算中假定为 4000 字节宽。这很可能会导致内存预留过多,从而限制并发,并将有价值的索引和数据页推出缓存内存
  • 禁用几个重要的性能优化
  • 可能会延长锁定持续时间
  • 可能会阻止优化器选择(非动态)搜索计划
  • 防止过滤器被推入扫描并作为残留物寻找
  • 可能会增加 tempdb 压力和争用(取决于版本),因为变量和参数也可能被键入max以匹配列定义

总而言之,不必要地使用说明max符会产生许多微妙的(和不受欢迎的)副作用,因此这样做毫无意义。使用单个声明的次要“方便”不是一种补偿。

在上下文中评估每种类型,使用正确的基本类型(varcharnvarchar),以及合理的显式长度。

进一步阅读:


Mat*_*don 8

这听起来像是偏执狂的答案,但不仅有存储和性能方面的考虑。

数据库本身不控制其客户端,并且不能假设客户端始终安全地插入用户输入 - 即使数据库设计为仅与使用实体框架封装事务并确保参数化查询的 .net 应用程序一起使用系统地使用,你不可能知道它总是会是这样。

我不会确切地知道如何做到这一点,但是通过制作所有文本字段varchar(max),如果客户端有Bobby Tables问题和/或您的存储过程的参数也是如此varchar(max),那么您就可以更容易地让攻击者想出一个有效但巧妙邪恶的参数值,它可以做客户不应该做的事情——不管那是什么。

通过将长度限制为您实际需要的长度,您并没有保护自己免受这些巧妙的攻击(我什至不确定它的实际名称是什么,我只记得前段时间读过它),但您并没有说“继续,尝试给我一个 2GB 的脚本来运行”。