SQL varchar列长度的最佳实践
VARCHAR(255)
和 VARCHAR(2)
在磁盘上占用的空间大小完全相同!因此,如果您没有特殊需要使其更小,则唯一的理由是限制它的大小。否则,请将它们全部设置为255。
具体而言,在进行排序时,更大的列确实占据更多的空间,因此如果这会影响性能,则需要考虑并使它们变小。但是,如果您仅从该表中选择1行,则可以将它们全部设置为255,这不会有影响。
我所了解的没有任何一个DBMS的“优化”会使一个长度为2^n的VARCHAR
比一个不是2的幂次方的max
长度更好。
我想早期的SQL Server版本实际上会对长度为255的VARCHAR
与最高长度不同的VARCHAR
进行不同处理。我不知道这是否仍然存在。
对于几乎所有DBMS,实际上所需的存储空间仅由您放入的字符数决定,并不取决于您定义的max
长度。因此,从存储点(很可能从性能的角度)来看,将列声明为VARCHAR(100)
或VARCHAR(500)
并没有任何区别。
您应该将提供给VARCHAR
列的max
长度视为一种约束(或业务规则),而不是一种技术/物理事物。
对于PostgreSQL,最佳设置是使用没有长度限制的text
和一个CHECK CONSTRAINT
,它将字符数量限制为您的业务需求。如果该要求更改,则更改检查约束要比更改表格快得多(因为无需重新编写表格)。
同样的方法也适用于Oracle和其他DBMS——在Oracle中,这将使用VARCHAR(4000)
而不是text
。
我不知道在SQL Server中使用VARCHAR(max)
与使用VARCHAR(500)
之间是否有物理存储差异。但显然,使用VARCHAR(max)
会对性能产生影响,与使用VARCHAR(8000)
相比。
请参见此链接 (由Erwin Brandstetter在评论中发布)
编辑于2013年9月22日
关于bigown的评论:
在我写出初始回答时,Postgres 9.2之前的版本(当时尚未推出)更改列定义会重写整个表,例如这里所述。自9.2版本以来,这种情况不再存在,快速测试确认增加具有120万行的表的列大小确实只需0.5秒即可完成。
对于Oracle,根据更改大表的varchar列所需的时间来判断好像也是如此。但我找不到任何参考资料。
对于MySQL,手册表示:“在大多数情况下,ALTER TABLE 会创建原始表的临时副本。”我的测试也证实了这一点:在具有1.2百万行的表上运行ALTER TABLE以增加列大小需要1.5分钟。但在MySQL中,您无法使用“变通方法”在列中限制字符数的检查约束。
对于SQL Server,我找不到明确的说明,但增加varchar列的执行时间(仍为上述120万行表)表明不进行重写。
编辑于2017-01-24
看来我对SQL Server的理解至少在一部分上是错误的。看看Aaron Bertrand 的这个回答,它表明声明nvarchar
或varchar
列的长度对于性能有很大影响。