我意识到,如果我的所有值都是固定宽度的,建议使用CHAR。但是,那又怎样?为了安全起见,为什么不为所有文本字段选择VARCHAR呢?
当前回答
一般规则是,如果所有行的长度接近相同,则选择CHAR。当长度变化显著时,选择VARCHAR(或NVARCHAR)。CHAR也可能更快一些,因为所有的行都是相同的长度。
它因数据库实现而异,但通常,VARCHAR(或NVARCHAR)除了实际数据之外,还会使用一到两个字节的存储空间(用于长度或终止)。因此(假设您使用的是单字节字符集)存储单词“FooBar”
CHAR(6) = 6字节(无开销) VARCHAR(100) = 8字节(2字节开销) CHAR(10) = 10字节(4字节浪费)
最重要的是,对于相对相同长度的数据(在两个字符长度差以内),CHAR可以更快、更节省空间。
注意:Microsoft SQL对于一个VARCHAR有2个字节的开销。这可能因DB而异,但通常至少需要1个字节的开销来指示VARCHAR上的长度或EOL。
正如Gaven在评论中指出的:当涉及到多字节字符集时,情况会发生变化,在这种情况下VARCHAR会成为更好的选择。
关于VARCHAR声明长度的注意事项:因为它存储了实际内容的长度,所以您不会浪费未使用的长度。因此,在VARCHAR(6)、VARCHAR(100)或VARCHAR(MAX)中存储6个字符使用相同的存储量。阅读更多关于使用VARCHAR(MAX)时的差异。在VARCHAR中声明最大大小以限制存储的容量。
在评论中AlwaysLearning指出Microsoft Transact-SQL文档似乎说的恰恰相反。我认为这是一个错误,或者至少文件不清楚。
其他回答
许多人指出,如果知道值的确切长度,使用CHAR会有一些好处。但是,虽然今天将美国州存储为CHAR(2)很棒,但当您从销售人员那里收到“我们刚刚完成了对澳大利亚的第一笔销售”的消息时,您将陷入痛苦的世界。我总是高估我认为字段需要多长时间,而不是做一个“准确”的猜测来覆盖未来的事件。VARCHAR将在这方面给我更多的灵活性。
在计算列值实际所需的大小和为Varchar分配空间时,会有一些小的处理开销,因此如果您确实确定值总是多长,那么最好使用Char并避免命中。
我支持吉姆·麦基思的评论。
此外,如果您的表只有CHAR列,那么索引和全表扫描会更快。基本上,优化器将能够预测每条记录有多大,如果它只有CHAR列,而它需要检查每个VARCHAR列的大小值。
此外,如果您将VARCHAR列更新到比其先前内容更大的大小,则可能会强制数据库重新构建其索引(因为您强制数据库将记录物理地移动到磁盘上)。而对于CHAR列,这种情况永远不会发生。
但是,除非表很大,否则您可能不会关心性能受到的影响。
记住吉布拉的至理名言。早期的性能优化是万恶之源。
一般规则是,如果所有行的长度接近相同,则选择CHAR。当长度变化显著时,选择VARCHAR(或NVARCHAR)。CHAR也可能更快一些,因为所有的行都是相同的长度。
它因数据库实现而异,但通常,VARCHAR(或NVARCHAR)除了实际数据之外,还会使用一到两个字节的存储空间(用于长度或终止)。因此(假设您使用的是单字节字符集)存储单词“FooBar”
CHAR(6) = 6字节(无开销) VARCHAR(100) = 8字节(2字节开销) CHAR(10) = 10字节(4字节浪费)
最重要的是,对于相对相同长度的数据(在两个字符长度差以内),CHAR可以更快、更节省空间。
注意:Microsoft SQL对于一个VARCHAR有2个字节的开销。这可能因DB而异,但通常至少需要1个字节的开销来指示VARCHAR上的长度或EOL。
正如Gaven在评论中指出的:当涉及到多字节字符集时,情况会发生变化,在这种情况下VARCHAR会成为更好的选择。
关于VARCHAR声明长度的注意事项:因为它存储了实际内容的长度,所以您不会浪费未使用的长度。因此,在VARCHAR(6)、VARCHAR(100)或VARCHAR(MAX)中存储6个字符使用相同的存储量。阅读更多关于使用VARCHAR(MAX)时的差异。在VARCHAR中声明最大大小以限制存储的容量。
在评论中AlwaysLearning指出Microsoft Transact-SQL文档似乎说的恰恰相反。我认为这是一个错误,或者至少文件不清楚。
除了性能方面的好处外,CHAR还可以用来表示所有值都应该是相同的长度,例如,美国州缩写的列。
推荐文章
- 在SQL Server 2008 R2中重命名数据库时出错
- 将数据复制到另一个表中
- 如何在SQL中选择表的最后一条记录?
- SQL在Oracle中连接多行列值的查询
- 修改列,添加默认约束
- 在单个查询中计算空值和非空值
- 在存储过程中使用“SET XACT_ABORT ON”有什么好处?
- SQL to LINQ工具
- 如何从一个查询插入多行使用雄辩/流利
- 如何连接列在Postgres选择?
- 有人可以对SQL查询进行版权保护吗?
- 如何知道MySQL表最近一次更新?
- 如何转储一些SQLite3表的数据?
- 如何创建一个SQL Server函数“连接”多行从一个子查询到一个单独的分隔字段?
- 在MySQL中的一个查询中更新多个具有不同值的行