设置varchar(8000)的后果是什么?

由于varchar字段占用的磁盘空间与字段大小成比例,是否有任何理由我们不应该总是将varchar定义为最大值,例如在SQL Server上使用varchar(8000)? 在创建表时,如果我看到有人使用varchar(100),我应该告诉他们不对,你应该使用varchar(8000)

我认为我们在这里需要区分在创建表时的用法和在存储过程参数声明中的用法。对于第二种解释,请参阅我的问题http://dba.stackexchange.com/questions/1772/which-problems-arise-declaring-the-size-of-all-varchar-parameters-as-max-in-stor - bernd_k
4个回答

  • 长度是对数据的限制(例如CHECK、FK、NULL等)
  • 当行超过8060字节时,性能会受到影响
  • 不能有唯一约束或索引(关键列宽度必须小于900)
  • 默认设置为SET ANSI PADDING ON = 可能会存储大量尾随空格
  • SQL Server假设排序操作的平均长度为4000,并根据此分配内存(需要找到一个链接来支持这一点,但请相信我在此期间 :-))

总结:不要这样做。


当行的字节数超过8060字节时,性能会受到影响。这指的是实际使用的字节数,而不是最大允许的字节数吗? - bernd_k
@bernd_k: 8060 = 单行数据中能适应单个8192页的最大数据量。包括行开销。剩余部分(132字节)= 页开销 - gbn
这意味着当真正使用更大的尺寸时,性能会下降,并不仅仅是因为允许使用它这个事实。 - bernd_k
@bernd_k:任何性能下降都是由以下原因引起的:1. 用于排序等操作的内存分配;2. 行溢出(>8060字节)。只有在满足这些条件后,每个varchar(8000)中有10个字符的事实才变得无关紧要(SQL会在后面对索引键发出潜在错误的警告)。 - gbn
对于一个填充有100字节长度字段的varchar(100)列进行排序是否值得另外考虑,因为排序假设平均字符数为50个? - bernd_k
@bernd_k: 我认为不是这样的。任何自重的数据库管理员在这种情况下都会使用char(100)吧?还可以参考http://sqlblog.com/blogs/paul_white/archive/2011/02/23/Advanced-TSQL-Tuning-Why-Internals-Knowledge-Matters.aspx(这是我能快速搜索到的最好的结果)。 - gbn

假设你指的是SQL Server,我能想到一个。

在表中,每行的大小有限制(8K),而SQL允许定义varchar字段,理论上可以超过该限制。因此,如果用户在与之相关的字段中放入过多的数据,则可能会出现错误。

从SQL 2K8开始,您可以超过这个限制,但会有性能影响

此外,对于将大小限制在预期数据外观范围内的合理性检查也很重要。如果您需要一个无界长度字段,为什么不使用text或ntext呢?


所以文本和ntext数据类型的存储方式不会影响性能吗? - Chad
这些类型对表的8K行大小限制的贡献不多,因为实际数据存储在一个单独的表中,而不是与其他列一起内联。尽管存在性能影响,但原因不同。与varchar和nvarchar相比,这些字段在功能支持方面也有限制。 - JohnFx
text和ntext已被弃用,推荐使用varchar(max)。 - Phil Helmer

当然,这取决于字段中存储的信息是什么? 出于各种原因,某些事物将具有最大长度,如果必须有最大长度,那么该长度应该是您字段的长度。 如果理论上没有最大长度,那么我会质疑为什么要使用varchar。

在Oracle数据库的背景下,我了解到始终使用最小的字段大小对于数据库列来说有一个缺陷。 当通过导入导出将数据从单字节排序的数据库移动到多字节排序的数据库(如Oracle XE)时,字节长度可能会增加,并且将数据导入由导入创建的表中会失败。当然,Oracle有选项可以将varchar2长度定义为char或byte。 我的观点是,并不总是明智地将字段定义为尽可能小。我见过很多后来需要通过alter tables来增加字段宽度的情况(由于需求变更引起)。 在这里,拥有20% - 100%未使用的字段宽度是一个值得讨论的选择。