Myisam 静态格式数据存储结构

Myisam 静态格式 数据的物理存储 行header 内部分析[@more@]
1. 从简单的例子开始
1.1 创建测试数据
drop table if exists heyf_5 ;
create table heyf_5 (id int , name char(10),addr char(20)) engine myisam DEFAULT CHARSET=latin1;
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 DEFAULT CHARSET=latin1;
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 --&gt 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',其它数据没有变.
疑问1: 在这里为什么只置6个字节? 为什么需要置这6个字节,光有header不能识别吗?

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
在这里我们看到了,被删除的空间马上得到了填充.
疑问2: MYSQL是怎么知道这行是可重复使用的,总不会每次INSERT的时候都去全表扫描吧?

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文件中).而且每个字段的长度都是固定的.所以读取应该相当容易.

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/703656/viewspace-1018253/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/703656/viewspace-1018253/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值