技术开发 频道

MYISAM 静态格式数据存储结构

  

       IT168技术文档1. 从简单的例子开始

  1.1 创建测试数据

  drop table if exists heyf_5 ;

  create table heyf_5 (id int , name char(10),addr char(20)) engine myisam ;

  insert into heyf_5 values (12,'hyf','street-1') ,(13,'steven','street-2') ;

  system hexdump /opt/mysql/data/test/heyf_5.MYD

  ------------------------------------------------

  0000000 0cf1 0000 6800 6679 2020 2020 2020 7320

  0000010 7274 6565 2d74 2031 2020 2020 2020 2020

  0000020 2020 f120 000d 0000 7473 7665 6e65 2020

  0000030 2020 7473 6572 7465 322d 2020 2020 2020

  0000040 2020 2020 2020

  -----------------------------------------------------

  --由于我们这一节讨论的是静态格式,我们这里取的数据类型都是固定长度的.

  1.2 开始读取数据

  --根据我们所定义的数据特征,我们能容易地从数据中分出各行:

  ROW1: 0cf1 0000 6800 6679 2020 2020 2020 7320 7274 6565 2d74 2031 2020 2020 2020 2020 2020 20

  ROW2: f1 000d 0000 7473 7665 6e65 2020 2020 7473 6572 7465 322d 2020 2020 2020 2020 2020 2020

  我们拿第一行数据来分析:

  由于数据存储在硬盘里时,双字节是低位先存储,高位后存储.所以我们读数据的时候要反过来一下:

  ROW1: f1 0c 00 00 00 68 79 66 20 20 20 20 20 20 20 73 74 72 65 65 74 2d 31 20 ... 20

  其中:

  -----------------------------------------------------

  f1 : Header (0>非NULL,1>NULL),

  在这里 1111 0001 ,其中三个"0"表示三个可空字段,并且没有为NULL的字段.

  --下面开始就是实际的值

  0c 00 00 00 : COLUMN ID INT , 4个字节,在这里表示12.

  68 79 66 20 20 20 20 20 20 20 : COLUMN name char(10) 20个字节 ,这里十六进制转换成字符刚好是"hyf",其它填空.

  73 74 72 65 65 74 2d 31 20 ... 20 : COLUMN addr char(20) ,20个字节

  -----------------------------------------------------

  有兴趣的同学们同样可以用同样的方法分析一下ROW2的数据.

  由于固定格式的数据,每个字段的长度都是固定的,所以读取数据的时候特别容易计算字段的长度和行的长度.

  2. 如果字段的值为NULL (行Header和字段值都发生变化)

  2.1 创建测试数据

  基于上面例子的数据,我们将第一行第三个字段的数据更新为空:

  update heyf_5 set addr = null where id=12 ;

  system hexdump /opt/mysql/data/test/heyf_5.MYD ;

  0000000 0cf9 0000 6800 6679 2020 2020 2020 2020

  0000010 2020 2020 2020 2020 2020 2020 2020 2020

  0000020 2020 f120 000d 0000 7473 7665 6e65 2020

  0000030 2020 7473 6572 7465 322d 2020 2020 2020

  0000040 2020 2020 2020

  我们取出第一行的数据来看:

  ROW1:0cf9 0000 6800 6679 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 20

  转换一下:

  f9 0c 00 00 00 68 79 66 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20

  其中:

  -------------------------------------------

  f9 : 标志位发生了变化: 1111 1001 ,其中的"100"表明第三个字段为NULL.

  0c 00 00 00 : 第1个字段未发生变化

  68 79 66 20 20 20 20 20 20 20 : 第2个字段未发生变化

  20 ....... 20 : 第3个字段都被置为了空.

  -------------------------------------------

  3. 如果字段类型为: NOT NULL

  drop table if exists heyf_5 ;

  create table heyf_5 (id int not null, name char(10) not null ,addr char(20) not null) engine myisam ;

  insert into heyf_5 values (12,'hyf','street-1') ,(13,'steven','street-2') ;

  system hexdump /opt/mysql/data/test/heyf_5.MYD

  0000000 0cff 0000 6800 6679 2020 2020 2020 7320

  0000010 7274 6565 2d74 2031 2020 2020 2020 2020

  0000020 2020 ff20 000d 0000 7473 7665 6e65 2020

  0000030 2020 7473 6572 7465 322d 2020 2020 2020

  0000040 2020 2020 2020

  对比1.1的测试数据,Header位发生了变化.

  1111 0001 --> 1111 1111

  查资料了解到:

  固定格式行的Header,是用来标识那些可空字段的实际值是否为NULL,如果是NULL,则填1.否则填0.

  如果表中没有"可NULL"字段,那么header="ff"

  Header长度= (1 + number of NULL columns + 7) / 8 bytes

  4. 如果行被删除了

  继续3的例子,我们删除第一行数据:

  delete from heyf_5 where id=12;

  system hexdump /opt/mysql/data/test/heyf_5.MYD

  0000000 ff00 ffff ffff 66ff 2020 2020 2020 7320

  0000010 7274 6565 2d74 2031 2020 2020 2020 2020

  0000020 2020 ff20 000d 0000 7473 7665 6e65 2020

  0000030 2020 7473 6572 7465 322d 2020 2020 2020

  0000040 2020 2020 2020

  我们发现header的值变成了"00",这就是一个行被DELETE的标志.

  但在我们同时注意到,第一行的数据,只有紧跟着Header后面6个字节被置成了'ff',其它数据没有变.

  5. 被删除后,空间重复使用

  继续4的例子,

  insert into heyf_5 values (23,'aaa','bbbb'),(34,'ccc','ddddd');

  system hexdump /opt/mysql/data/test/heyf_5.MYD

  0000000 17ff 0000 6100 6161 2020 2020 2020 6220

  0000010 6262 2062 2020 2020 2020 2020 2020 2020

  0000020 2020

  ff20 000d 0000 7473 7665 6e65 2020

  0000030 2020 7473 6572 7465 322d 2020 2020 2020

  0000040 2020 2020 2020

  22ff 0000 6300 6363 2020

  0000050 2020 2020 6420 6464 6464 2020 2020 2020

  0000060 2020 2020 2020 2020 0020

  在这里我们看到了,被删除的空间马上得到了填充.

  6. 小结

  通过上面的实例分析,我们对MYISAM这种引擎的固定长度数据存储作了一个的了解.

  6.1 行组成

  固定长度的行格式: 行Header + 数据部分

  6.2 行的长度

  行header的长度=(1 + number of NULL columns + 7) / 8 bytes

  数据部分长度根据用户的定义计算

  6.3 行header的作用

  在固定格式的行中,行header主要是用来标识

  1) 该行是否被删除,如果行被删除会被置为"00"

  2) 该行中"可NULL"字段的实际值是否为NULL,(0>NOT NULL,1> NULL)

  6.4 行数据部分的读取

  在行header后面就是数据部分,

  所有字段是根据用户的定义顺序来存储的(记录在.FRM文件中).而且每个字段的长度都是固定的.所以读取应该相当容易.

0
相关文章