我正在使用Django并设置我的CharField( max_length = 255 ),即使我只打算使用大约5个字符。这效率不高吗?我已经读过它与varchar无关,但后来读到它会节省硬盘空间,只能指定你需要的东西。
答案 0 :(得分:12)
通常,varchar(255)需要与varchar(1)一样多的存储空间。在每种情况下,表都存储类似指针到字符串表和长度的东西。例如。 4字节偏移+ 1字节大小=每行固定5个字节,仅用于开销。
实际内容当然是在字符串表中,它只与您在其中存储的字符串一样长。因此,如果您在varchar(255)字段中存储5个字母的名称,它将仅使用(比方说)5个开销字节+5个内容字节= 10个字节。
使用varchar(10)字段将使用完全相同的数量,但只会截断超过10个字节的字符串。
当然,具体数字取决于存储引擎的实现。
答案 1 :(得分:4)
除了overhead for storing the string length之外,varchar不会占用比你存储在其中的字符串更多的空间:
+------------------------------------------+---------------------------------+
| Value | CHAR(4) Storage Required | VARCHAR(4) Storage Required |
+------------+-----------------------------+---------------------------------+
| '' | ' ' 4 bytes | '' 1 byte |
| 'ab' | 'ab ' 4 bytes | 'ab' 3 bytes |
| 'abcd' | 'abcd' 4 bytes | 'abcd' 5 bytes |
| 'abcdefgh' | 'abcd' 4 bytes | 'abcd' 5 bytes |
+------------+-----------------------------+---------------------------------+
但是,如果您确实只需要5个字符,那么如果表中没有其他可变宽度列(即varchars,text或blobs),请考虑使用char(5)。那么你将有固定的长度记录,它带有一些performance advantages:
对于更改的MyISAM表 经常,你应该尽量避免 所有可变长度列(VARCHAR, BLOB和TEXT)。该表使用 动态行格式,如果它包括偶数 一个可变长度的列。看到 第13章,存储引擎。
答案 2 :(得分:2)
关于使用char而不是varchar的一个警告是字符集会影响必须分配的空间。例如,如果该列的字符集是utf8,那么存储单个字符可能需要3个字节。
由于char列导致固定大小分配而不管存储的是什么,因此数据库必须适应最坏的情况。因此,MySQL必须始终为该char(5)列分配每行15个字节,即使您实际上每行只存储5个单字节字符。
varchar使用每行所需的内容,因此相同的5个单字节字符只占用6或7个字节。额外的一个或两个字节用于跟踪实际长度。对于单字节字符集中宽度最大为255的varchar,MySQL需要仅分配1个字节来存储实际宽度。假设单字节字符集,宽度为256到65,535的varchar需要2个字节来存储长度。
由于utf8 varchar(255)可能需要255 * 3字节的存储空间,因此MySQL必须分配2个字节来存储长度。 MySQL文档here中涵盖了大部分信息。
虽然您可以声明宽度为65,535,但最大有效大小(以字节为单位)为65,532。但是,根据字符集和存储的字符,您可以存储的字符数最多可以少于多个字节。
正如保罗指出的那样,如果允许整个行固定宽度,你可能仍然想要使用字符。除其他事项外,由于固定偏移,某些搜索可以更快(例如,跳过前1000行)。
对于列的更新,还有一些性能问题需要考虑。如果您有一个char(5)并以1个字符开头,然后将该值更新为5个字符,则可以在适当的位置更新该行。使用varchar,根据存储引擎实现,可能需要在新位置重写整行。
最后,如果MySQL需要创建一个内存临时表来对持久表中的结果集进行排序,它会使用固定长度的记录。因此,它为内存中的超大varchar列分配了比您想象的更多的空间。内存存储引擎表的MySQL文档中对此进行了介绍。我相信MySQL也会为基于磁盘的排序做这件事。
答案 3 :(得分:1)
硬盘空间很便宜,但CPU缓存空间很贵。您可以使用比较大字段更小的字段。
答案 4 :(得分:0)
不要不必要地使用大空间,而是利用空间不仅可以提供更多的存储空间,而且还可以快速执行,因为它不需要读取所有字符。 如果你分配varchar(255)并添加文本'abc',它将读取字符'a','b','c'和其他作为空格。
因此,请始终使用所需的空间,而不是保留最大空间。