我意识到,如果我的所有值都是固定宽度的,建议使用CHAR。但是,那又怎样?为了安全起见,为什么不为所有文本字段选择VARCHAR呢?


当前回答

There are performance benefits, but here is one that has not been mentioned: row migration. With char, you reserve the entire space in advance.So let's says you have a char(1000), and you store 10 characters, you will use up all 1000 charaters of space. In a varchar2(1000), you will only use 10 characters. The problem comes when you modify the data. Let's say you update the column to now contain 900 characters. It is possible that the space to expand the varchar is not available in the current block. In that case, the DB engine must migrate the row to another block, and make a pointer in the original block to the new row in the new block. To read this data, the DB engine will now have to read 2 blocks. No one can equivocally say that varchar or char are better. There is a space for time tradeoff, and consideration of whether the data will be updated, especially if there is a good chance that it will grow.

其他回答

当使用varchar值时,SQL Server每行需要额外的2个字节来存储关于该列的一些信息,而如果使用char则不需要 所以除非你

我会选择varchar,除非列存储固定的值,如美国州代码-这总是2个字符长,有效的美国州代码列表不经常改变:)。

在其他情况下,甚至像存储哈希密码(固定长度),我会选择varchar。

为什么——char类型的列总是用空格填充,这使得列my_column定义为char(5),值为'ABC'在比较中:

my_column = 'ABC' -- my_column stores 'ABC  ' value which is different then 'ABC'

假的。

这个特性可能会在开发过程中导致许多恼人的bug,并使测试更加困难。

我永远不会使用字符。我和很多人都有过这样的争论,他们总是提出令人厌倦的cliché char更快。我说,快多少?我们在这里讨论的是什么,毫秒,秒,如果是的话,是多少?你是在告诉我,因为有人声称它快了几毫秒,我们就应该在系统中引入大量难以修复的bug ?

这里有一些你会遇到的问题:

每个字段都将被填充,因此您最终得到的代码将永远到处都是RTRIMS。对于较长的字段来说,这也是一种巨大的磁盘空间浪费。

现在假设你有一个典型的例子,一个只有一个字符的char字段,但是这个字段是可选的。如果有人传递一个空字符串到这个字段,它就变成了一个空格。因此,当另一个应用程序/进程查询它时,如果不使用rtrim,它们将得到一个单独的空间。我们有xml文档,文件和其他程序,只显示一个空格,在可选字段和打破东西。

现在你要确保传递给char字段的是空值而不是空字符串。但这不是null的正确用法。这里是null的用法。假设您从供应商那里获得了一个文件

城市名字性别| |

鲍勃| |洛杉矶

如果没有指定性别,则在表中输入Bob、空字符串和Los Angeles。现在让我们假设你得到了文件,它的格式改变了,性别不再包括在内,而是在过去。

城市名称|

鲍勃|西雅图

好吧,现在由于性别不包括在内,我将使用null。Varchars毫无问题地支持这一点。

而夏尔则不同。你总是要发送null。如果你发送空字符串,你将得到一个包含空格的字段。

我可以继续在大约20年的开发过程中修复所有的错误。

碎片。Char会保留空间,而VarChar则不会。为了适应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文档似乎说的恰恰相反。我认为这是一个错误,或者至少文件不清楚。