标签:数据存储 innodb compact redundant
InnoDB行格式分两种格式(COMPACT,redundant)默认为COMPACT compact的存储格式为 首部为一个非NULL的变长字段长度列表,而且是按照列的顺序逆序放置的,当列的长度小于255字节,用1字节表示,若大于255个字节。用2个字节表 示,varchar的最大长度为65535>,因为两个字节为16位,即65535,第二部分是NULL标志位,该位指示了该行是否有NULL值, 有用01表示,无则用00表示。接下去的部分是为记录头信息(record header)固定占用5个字节,最后的部分就是实际存储的每个列的数据,NULL不占该部分任何数据,除了占有NULL标志位,实际存储不占任何空间, 另外注意,每行数据除了用户定义的列外,还有两个隐 藏列,事务ID(6字节),会滚指针列(7字节),若INNODB表没有定义,Primay key,那么每行会增加一个6字节的rowid,如果有,怎有4个字节的索引字段。PS:null不占用空间
我们观察下第三列存的数据:03,01表示第四列和第一列不为空,06表示存在null值,为止在于第二位和第三位,00000110 = 06
接下来我们看下数据被删除后空间的变化情况:
lin_ren@test 12:19:09>select * from test1;
t1 t2 t3
t4
a bb bb
ccc
d ee ee
fff
d NULL
NULL fff
3 rows in set (0.00 sec)
xue_binbin@test 12:27:40>delete from test1 where t1 = ‘a‘;
Query OK, 1 row affected (0.00 sec)
0000c070 73 75 70 72 65 6d 75 6d 03 02 01 00 20 00 10 00 |supremum.... ...|
0000c080 00 00 00 0c 84 58 00 00 00 00 63 60 0c 00 00 00 |.....X....c`....|
0000c090 00 33 26 06 61 62 62 62 62 20 20 20 20 20 20 20 |.3&.abbbb |
0000c0a0 20 63 63 63 03 02 01 00 00 00 18 00 2b 00 00 0c | ccc........+...|
0000c0b0 84 58 01 00 00 00 62 7c 94 80 00 00 00 2d 01 1f |.X....b|.....-..|
0000c0c0 64 65 65 65 65 20 20 20 20 20 20 20 20 66 66 66 |deeee fff|
0000c0d0 03 01 06 00 00 20 ff 98 00 00 0c 84 58 02 00 00 |..... ......X...|
0000c0e0 00 62 7c 94 80 00 00 00 2d 01 2e 64 66 66 66 00 |.b|.....-..dfff.|
0000c0f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
我们发现数据存储没有变化
xue_binbin@test 12:35:01>insert into test1 values(‘a‘,‘bb‘,‘bb‘,‘ccc‘);
Query OK, 1 row affected (0.00 sec)
xue_binbin@test 12:35:08>select * from test1;
t1 t2 t3
t4
d ee ee
fff
d NULL
NULL fff
a bb bb
ccc
0000c070 73 75 70 72 65 6d 75 6d 03 02 01 00 00 00 10 ff |supremum........|
0000c080 ef 00 00 0c 84 58 0c 00 00 00 63 63 8f 80 00 00 |.....X....cc....|
0000c090 00 2d 01 10 61 62 62 62 62 20 20 20 20 20 20 20 |.-..abbbb |
0000c0a0 20 63 63 63 03 02 01 00 00 00 18 00 2b 00 00 0c | ccc........+...|
0000c0b0 84 58 01 00 00 00 62 7c 94 80 00 00 00 2d 01 1f |.X....b|.....-..|
0000c0c0 64 65 65 65 65 20 20 20 20 20 20 20 20 66 66 66 |deeee fff|
0000c0d0 03 01 06 00 00 20 ff a9 00 00 0c 84 58 02 00 00 |..... ......X...|
0000c0e0 00 62 7c 94 80 00 00 00 2d 01 2e 64 66 66 66 00 |.b|.....-..dfff.|
由此表明数据空间删除的时候不释放,在等着下一个插入数据时刻,如果插入相同的数据就可以重复利用,如果没有,就有碎片
xue_binbin@test 12:35:13>insert into test1 values(‘c‘,‘aaa‘,‘aaa‘,‘cc‘);
Query OK, 1 row affected (0.00 sec)
xue_binbin@test 12:37:24>select * from test1;
0000c070 73 75 70 72 65 6d 75 6d 03 02 01 00 00 00 10 00 |supremum........|
0000c080 77 00 00 0c 84 58 0c 00 00 00 63 63 8f 80 00 00 |w....X....cc....|
0000c090 00 2d 01 10 61 62 62 62 62 20 20 20 20 20 20 20 |.-..abbbb |
0000c0a0 20 63 63 63 03 02 01 00 00 00 18 00 2b 00 00 0c | ccc........+...|
0000c0b0 84 58 01 00 00 00 62 7c 94 80 00 00 00 2d 01 1f |.X....b|.....-..|
0000c0c0 64 65 65 65 65 20 20 20 20 20 20 20 20 66 66 66 |deeee fff|
0000c0d0 03 01 06 00 00 20 ff a9 00 00 0c 84 58 02 00 00 |..... ......X...|
0000c0e0 00 62 7c 94 80 00 00 00 2d 01 2e 64 66 66 66 02 |.b|.....-..dfff.|
0000c0f0 03 01 00 00 00 28 ff 78 00 00 0c 84 58 0d 00 00 |.....(.x....X...|
0000c100 00 63 64 b5 80 00 00 00 2d 01 10 63 61 61 61 61 |.cd.....-..caaaa|
0000c110 61 61 20 20 20 20 20 20 20 63 63 00 00 00 00 00 |aa cc.....|
由此可见,如果插入一条新的数据,则会接着往下空间存
接着我们来看下有主键的情况的INNODB存储情况:
CREATE TABLE te1 (
id int(11) NOT NULL DEFAULT ‘0‘,
t1 varchar(10) DEFAULT NULL,
t2 varchar(10) DEFAULT NULL,
t3 char(6) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT
insert into te1 values(1,‘aa‘,‘bb‘,‘bb‘);
insert into te1 values(2,‘cc‘,NULL,NULL);
同样的分析数据: 0000c070 73 75 70 72 65 6d 75 6d 02 02 00 00 00 10 00 26 |supremum.......&|
0000c080 80 00 00 01 00 00 00 62 98 e7 80 00 00 00 2d 01 |.......b......-.|
0000c090 10 61 61 62 62 62 62 20 20 20 20 20 20 20 20 02 |.aabbbb .|
0000c0a0 06 00 00 18 ff ca 80 00 00 02 00 00 00 62 99 2e |.............b..|
0000c0b0 80 00 00 00 2d 01 10 63 63 00 00 00 00 00 00 00 |....-..cc.......|
0000c0c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
我们发现如果有主键的话,在头文件(00 00 10 00 26)会有记录索引的信息(所有的记录行80 00 00 01)01表示主键1,将比没有索引的少存一个字节
xue_binbin@test 12:44:05>update te1 set t1 =‘cc‘ where id = 1;
Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0
0000c070 73 75 70 72 65 6d 75 6d 02 02 00 00 00 10 00 22 |supremum......."|
0000c080 80 00 00 01 00 00 00 63 68 c3 00 00 00 00 33 0f |.......ch.....3.|
0000c090 a7 63 63 62 62 62 62 20 20 20 20 02 06 00 00 18 |.ccbbbb .....|
0000c0a0 ff ce 80 00 00 02 00 00 00 63 31 07 80 00 00 00 |.........c1.....|
0000c0b0 2d 01 1d 63 63 00 00 00 00 00 00 00 00 00 00 00 |-..cc...........|
由此可见,update操作是在原有的数据位置上做更改操作,不会产生碎片
冗余(redundant)
xue_binbin@test 11:00:55>create table test3 engine = innodb row_format = redundant as select * from test1;
xue_binbin@test 07:40:21>select * from test3;
t1 t2 t3
t4
a bb bb
ccc
d ee ee
fff
d NULL
NULL fff
同样分析数据:
0000c070 08 03 00 00 73 75 70 72 65 6d 75 6d 00 23 20 16 |....supremum.# .|
0000c080 14 13 0c 06 00 00 10 0f 00 ba 00 00 0c 84 58 06 |..............X.|
0000c090 00 00 00 63 40 0a 80 00 00 00 2d 01 10 61 62 62 |...c@.....-..abb|
0000c0a0 62 62 20 20 20 20 20 20 20 20 63 63 63 23 20 16 |bb ccc# .|
0000c0b0 14 13 0c 06 00 00 18 0f 00 ea 00 00 0c 84 58 07 |..............X.|
0000c0c0 00 00 00 63 40 0a 80 00 00 00 2d 01 1f 64 65 65 |...c@.....-..dee|
0000c0d0 65 65 20 20 20 20 20 20 20 20 66 66 66 21 9e 94 |ee fff!..|
0000c0e0 14 13 0c 06 00 00 20 0f 00 74 00 00 0c 84 58 08 |...... ..t....X.|
0000c0f0 00 00 00 63 40 0a 80 00 00 00 2d 01 2e 64 00 00 |...c@.....-..d..|
0000c100 00 00 00 00 00 00 00 00 66 66 66 00 00 00 00 00 |........fff.....|
0000c110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
test3表中第一行记录为(a,bb,bb,ccc)他们的长度分别为1,2,10,3
外加上还有隐藏的三个字段(rowid(长度为6),事务ID(6),回滚ID(7))
所以长度偏移列表有7个,分别为(06)6,(0c)12,(13)19,(14)20,(16)22,(20)32,(23)35
表空间数据记录为反序,则为23,20,16,14,13,0c,06
23 20 16 14 13 0c 06 长度偏移列表
00 00 10 0f 00 ba 头文件ID
00 00 0c 84 58 06 rowid
00 00 00 63 40 0a transactionID
80 00 00 00 2d 01 10 回滚ID
至于主键的话,同样的把rowid换成了4个字节的主键信息
对于插入的数据的顺序,底层是怎么插入的?
实验: create table t3(id int not null,t1 varchar(10) CHARACTER SET latin1 DEFAULT NULL,t2 varchar(10) CHARACTER SET latin1 DEFAULT NULL,t3 char(6) CHARACTER SET latin1 DEFAULT NULL,PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=compact;
lin_ren@test 05:52:24>insert into t3 values(1,‘aa‘,‘bb‘,‘cc‘);
Query OK, 1 row affected (0.00 sec)
lin_ren@test 05:53:39>insert into t3 values(3,‘aaa‘,‘bbb‘,‘ccc‘);
Query OK, 1 row affected (0.00 sec)
lin_ren@test 05:54:50>insert into t3 values(2,‘aa‘,‘bbbb‘,‘ccc‘);
Query OK, 1 row affected (0.00 sec)
0000c070 73 75 70 72 65 6d 75 6d 02 02 00 00 00 10 00 48 |supremum.......H|
0000c080 80 00 00 01 00 00 00 82 46 58 80 00 00 00 32 01 |........FX....2.|
0000c090 10 61 61 62 62 63 63 20 20 20 20 03 03 00 00 00 |.aabbcc .....|
0000c0a0 18 ff cd 80 00 00 03 00 00 00 82 46 65 80 00 00 |...........Fe...|
0000c0b0 00 32 01 10 61 61 61 62 62 62 63 63 63 20 20 20 |.2..aaabbbccc |
0000c0c0 04 02 00 00 00 20 ff db 80 00 00 02 00 00 00 82 |..... ..........|
0000c0d0 46 8a 80 00 00 00
32 01 10 61 61 62 62 62 62 63 |F.....2..aabbbbc|
0000c0e0 63 63 20 20 20 00 00 00 00 00 00 00 00 00 00 00 |cc ...........|
0000c0f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
CREATE TABLE t1 (
id int(11) NOT NULL DEFAULT ‘0‘,
t1 varchar(10) CHARACTER SET latin1 DEFAULT NULL,
t2 varchar(10) CHARACTER SET latin1 DEFAULT NULL,
t3 char(6) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=REDUNDANT |
lin_ren@test 05:57:17>insert into t1 values(1,‘aa‘,‘bb‘,‘cc‘);
Query OK, 1 row affected (0.00 sec)
lin_ren@test 06:03:43>insert into t1 values(3,‘a‘,‘b‘,‘c‘);
Query OK, 1 row affected (0.00 sec)
lin_ren@test 06:04:01>insert into t1 values(2,‘aa‘,‘ab‘,‘cc‘);
Query OK, 1 row affected (0.00 sec)
0000c070 08 03 00 00 73 75 70 72 65 6d 75 6d 00 1b 15 13 |....supremum....|
0000c080 11 0a 04 00 00 10 0d 00 d5 80 00 00 01 00 00 00 |................|
0000c090 82 46 d3 80 00 00 00 32 01 10 61 61 62 62 63 63 |.F.....2..aabbcc|
0000c0a0 20 20 20 20 19 13 12 11 0a 04 00 00 18 0d 00 74 | ...........t|
0000c0b0 80 00 00 03 00 00 00 82 46 d5 80 00 00 00 32 01 |........F.....2.|
0000c0c0 10 61 62 63 20 20 20 20 20 1b 15 13 11 0a 04 00 |.abc .......|
0000c0d0 00 20 0d 00 b0 80 00 00 02 00 00 00 82 46 d6 80 |. ...........F..|
0000c0e0 00 00 00 32 01 10 61 61 61 62 63 63 20 20 20 20 |...2..aaabcc [BR]]
由此可见,不管是compact,还是redundant ,用ID做主键,插入的顺序按照你的排列顺序,而不是按照id的顺序排列
optimize table t3;
lin_ren@test 10:16:09>optimize table t3;
Table Op
Msg_type Msg_text
test.t3 optimize
note Table does not support optimize, doing recreate + analyze instead
test.t3 optimize
status OK
整理后数据排序
0000c070 73 75 70 72 65 6d 75 6d 02 02 00 00 00 10 00 23 |supremum.......#|
0000c080 80 00 00 01 00 00 00 82 5f ff 80 00 00 00 32 01 |........_.....2.|
0000c090 10 61 61 62 62 63 63 20 20 20 20 04 02 00 00 00 |.aabbcc .....|
0000c0a0 18 00 25 80 00 00 02 00 00 00 82 5f ff 80 00 00 |..%........_....|
0000c0b0 00 32 01 1d 61 61 62 62 62 62 63 63 63 20 20 20 |.2..aabbbbccc |
0000c0c0 03 03 00 00 00 20 ff a8 80 00 00 03 00 00 00 82 |..... ..........|
0000c0d0 5f ff 80 00 00 00 32 01 2a 61 61 61 62 62 62 63 |_.....2.*aaabbbc|
0000c0e0 63 63 20 20 20 00 00 00 00 00 00 00 00 00 00 00 |cc ...........|
删除数据:
optimize table t3;
0000c000 6e 94 df 09 00 00 00 03 ff ff ff ff ff ff ff ff |n...............|
0000c010 00 00 00 5a 29 eb 95 68 45 bf 00 00 00 00 00 00 |...Z)..hE.......|
0000c020 00 00 00 00 16 c9 00 02 00 c0 80 04 00 00 00 00 |................|
0000c030 00 a3 00 02 00 01 00 02 00 00 00 00 00 00 00 00 |................|
0000c040 00 00 00 00 00 00 00 00 38 2f 00 00 16 c9 00 00 |........8/......|
0000c050 00 02 00 f2 00 00 16 c9 00 00 00 02 00 32 01 00 |.............2..|
0000c060 02 00 1d 69 6e 66 69 6d 75 6d 00 03 00 0b 00 00 |...infimum......|
0000c070 73 75 70 72 65 6d 75 6d 02 02 00 00 00 10 00 23 |supremum.......#|
0000c080 80 00 00 01 00 00 00 82 60 50 80 00 00 00 32 01 |........`P....2.|
0000c090 10 61 61 62 62 63 63 20 20 20 20 04 02 00 00 00 |.aabbcc .....|
0000c0a0 18 ff cd 80 00 00 02 00 00 00 82 60 50 80 00 00 |...........`P...|
0000c0b0 00 32 01 1d 61 61 62 62 62 62 63 63 63 20 20 20 |.2..aabbbbccc |
0000c0c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
由此可见,如果删除大量的数据,我们要执行optimize table t3操作来释放空间。
以上就是InnoDB行格式分两种格式(COMPACT,redundant)的区别,外加Insert,delete,update的本质区别。
InnoDB行格式(compact,redundant)对比
标签:数据存储 innodb compact redundant
原文地址:http://blog.csdn.net/hustyangju/article/details/39696081