日期:2014-05-16  浏览次数:20755 次

Mysql 中各类型数据的的存储需求
首先,数据库中每行最大长度不能超过65535bytes,其中Blob和Text的数据只占用9到12byte(具体大小不知道和什么有关系)。

Char(M)的长度计算比较简单,但也要详细说一下,M是字符的个数(不能超过255),而不是byte数,因此它的实际存储容量和它所使用的字符集有关系,对于像utf8这样的字符集(每个字符没有固定的长度),他的容量V应该如何计算?这里简单的V = M * w,其中w是字符集中每个字符占用的最大byte数,对于utf8应该是3吧,我原来猜测既然像char(4)这样的数据最大能容纳4*3bytes(对于utf8字符集),那么他肯定能容纳’123456’这段数据,因为他用utf8字符集表示也不过占用6bytes。但是实际测试后发现不是,不管是数字还是字母或者汉字,他最多只能容纳4个。

然后我们重点关注一下varchar(M)的长度,因为它的长度很不固定而且使用范围最广。这里的M的范围理论上限制在0到65535之间,为什么说理论上,是因为它的实际长度要受很多因素的限制,比如每行最大长度,使用的字符集,以及M。我们拿 varchar(127)来作为例子,假设他使用gbk字符集,他的最大可能长度应该是127*2=254,但是因为他需要有一个prefix来表示他具体bytes数是多少(因为varchar是变长的,没有这个长度值他不知道如何读取数据),因此分配1byte来表示他的bytes数为254,这样他最终占用的byte数为255,如果是varchar(128),2*128 = 256这个数字用一个byte无法表示,因此需要2个byte的prefix,这样他会占用258bytes。而如果他改使用latin1字符集,那么每个字符为1个字节,这样它的最大可能长度为1* 128 < 256,可以用一个byte表示它的长度,因此他又占用129bytes。

这里的M最大能是多少呢?对于latin1的字符,因为每个字符占一个字节,而max row size 为65535,所以M最大为65535-2 = 65533(2是prefix的长度,这个65535其实还和这一行中其他列的长度有关,准确的说应该是65535减去其他列的长度,但这里简单将他们忽略)。而如果使用utf8字符,字符最大占用3个字节,那么M最大应该是(65535 – 2)/3 = 21844,这里的2是prefix的长度。

对于某些数据库引擎,他的数据存取空间大小还需要考虑align的情况,比如计算的大小是15,但他的align = 4,所以它最后会占用16bytes。