MySQL表设计优化与索引 (四)

String Types(字符串类型)

字符串类型

Mysql支持多种字符串类型的变体。 这些数据类型在4.1和5.0版本中有较大的变化, 这使得这些数据类型变得更加复杂。 从Mysql4.1起, 每个字符串类型能有自己的字符集和针对这些字符集的排序规则集 (更多的关于排序规则的主题, 参考第5章), 这对于性能有较大的影响。

VARCHAR和CHAR类型

VARCHAR和CHAR是两种最主要的存储字符串的数据类型, 不幸的是,的确有些困难解释这两种数据类型在磁盘和内存中是如何存储的, 因为这是与存储引擎相关的(比如, Falcon的差不多所有数1是, 请参考相应的存储引擎文档。

先看看VARCHAR和CHAR值的典型的磁盘存储方式。 同一种存储引擎对VARCHAR和CHAR在磁盘和内存中的存储格式可能是不一样的, 当从一个地方读取并存到另一个地方时, 服务器可能需要做一些转换工作。 两种数据类型的一些比较:

VARCHAR存储可变长度的字符串, 它应该是最为常见的数据类型了。 相对于固定长度的数据类型, 它需要的存储恐空间相对较少, 因为它按需分配存储空间 (比如, 存储短字符串的时候就用少的空间). 例外的地方在MyISAM中建立ROW_FORMAT=FIXED的表, 这种表对于每一行都使用相同数量空间来存储, 因而会导致空间浪费。VARCHAR 使用1或2个字节来记录值的长度: 如果字段的长度小于255个字节, 用1个字节, 否则用2个字节。假定使用latin1字符集, 一个VARCHAR(10)的字段值使用11个字节的存储空间, 1个VARCHAR(1000)的字段值使用1002字节的空间, 因为需要2个字节来存储长度信息。

VARCHAR有助于改善性能, 因为能节省空间。 但是, 因为记录的长度是可变的, 当修改的时候因为记录可能变长会导致一些额外的工作。 如果一列增长了而原来的存储空间不能存储修改后的值, 具体的增长策略是与具体的存储引擎相关的。 比如, MyISAM可能导致分行, 而innodb则可能会导致分页来处理。 其他的一些引擎则可能不会在原来的地方修改数据。

一般来说, 当某个字段的最大长度远远大于平均长度时; 或者很少修改字段因为碎片化不会是一个问题; 或者使用一个复杂的字符集合比如UTF-8, 而每个字符使用变长的字节来表示时, 使用VARCHAR来存储时值得的。

CHAR是固定长度的, Mysql总是分配足够的空间来存储指定数目的字符。当存储一个CHAR值时, Mysql会除去尾随空间(在4.1以及之前的版本, VARCHAR也是这么处理的, VARCHAR和CHAR逻辑上市一样的,只是存储格式不一样而已.) 当比较时, 字段后面会根据需要垫加一些空格来进行比较。

当需要存储非常短的字符串时; 或者所有的字段值差不多同样长时, CHAR非常有用。比如, 用CHAR来存储用户密码的md5结果值, 这些结果值是等长的。 当字段值长度变化频繁时, CHAR比VARCHAR要好, 因为固定长度的字段不容易导致碎片化。 对一些字段值很短的字段, CHAR也比VARCHAR高效, 用CHAR(1)来存储Y或者N只需要一个字节长度来存储数据, 而VARCHAR(1)则需要2个字节,因为需要一个字节来表示长度。