11

我正在使用 Django 并设置我的 CharField( max_length=255 ),即使我只打算使用大约 5 个字符。这效率低吗?我读过 varchar 并不重要,但后来读到它会节省硬盘空间以仅指定您需要的内容。

4

5 回答 5

14

通常,varchar(255) 需要与 varchar(1) 一样多的存储空间。在每种情况下,该表都存储了诸如指向字符串表的指针和长度之类的东西。例如 4 字节偏移 + 1 字节大小 = 每行固定 5 字节,仅用于开销。

实际的内容当然是在字符串表中,只要你在其中存储的字符串就行了。因此,如果您在 varchar(255) 字段中存储 5 个字母的名称,它只会使用(比如说)5 个开销字节 + 5 个内容字节 = 10 个字节。

使用 varchar(10) 字段将使用完全相同的数量,但只会截断超过 10 个字节的字符串。


当然,具体数字取决于存储引擎的实现。

于 2010-01-13T08:37:57.863 回答
5

除了存储字符串长度的开销之外,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 或 blob),请考虑使用 char(5)。然后您将拥有固定长度的记录,这确实具有一些性能优势

对于频繁更改的 MyISAM 表,您应该尽量避免使用所有可变长度列(VARCHAR、BLOB 和 TEXT)。如果该表甚至包含单个可变长度列,则该表使用动态行格式。请参阅第 13 章,存储引擎。

于 2010-01-13T09:29:06.570 回答
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 文档中进行了介绍。

虽然您可以声明宽度为 65,535,但最大有效大小(以字节为单位)为 65,532。但是,根据您存储的字符集和字符,您最多可以存储比这少得多的多字节字符。

但是,正如 Paul 指出的那样,如果允许整行固定宽度,您可能仍想使用 char。除此之外,由于固定偏移量,某些查找可以更快(例如,跳过前 1000 行)。

围绕列的更新还需要考虑性能问题。如果您有一个 char(5) 并以 1 个字符开头,然后将值更新为 5 个字符,则可以就地更新该行。对于 varchar,根据存储引擎的实现,可能需要在新位置重写整行。

最后,如果 MySQL 需要创建一个内存临时表来对持久表中的结果集进行排序,它会使用固定长度的记录。因此,它为那些超大的 varchar 列分配了比您想象的更多的内存空间。内存存储引擎表的 MySQL 文档对此进行了介绍。我相信 MySQL 也会为基于磁盘的排序做到这一点。

于 2010-01-29T08:36:17.587 回答
1

硬盘空间便宜,但 CPU 缓存空间昂贵。与较大的字段相比,您可以容纳更多的较小字段。

于 2010-01-13T08:29:22.957 回答
0

与其不必要地使用大空间,不如利用空间,不仅可以为您提供更多存储空间,而且还可以加快执行速度,因为它不需要读取所有字符。如果分配 varchar(255) 并添加文本 'abc',它将读取字符 'a'、'b'、'c' 和其他字符作为空格。

因此,请始终使用所需的空间,而不是保持最大空间。

于 2010-01-13T09:22:29.660 回答