主要介绍innodb存储引擎表的逻辑存储以及实现。重点介绍数据在表中是如何组织和存放的。
1.索引组织表(index organized table)
在innodb存储引擎中,表都是根据主键顺序组织存放的,这种存储方式的表叫索引组织表。在innodb存在引擎表中,每张表都有个主键(primary key),如果在创建表时没有显示定义主键,则会按照如下方式选择或者创建主键:a.判定是否有非空的唯一索引(unique not null),如果有则该列即为主键。若果有多个,则选择建表是第一个定义的非空位于索引为主键。注意:主键的选择根据的是定义索引的顺序,而不是建表时的列的顺序。 b.如果不存在唯一索引,innodb存储引擎字段创建一个6字节大小的指针。
2.innodb逻辑存储结构
在innodb存储引擎中,所有的数据都被逻辑地存放在一个空间中,称之为表空间(tablespace)。表空间又由段(segment)、区(extent)、页(page)组成。页在一些文档中有时也称之为块(block)。innodb存储引擎的逻辑存储结构如下图。
vc/m2mri0ts689tavenj3kgjts62vmrh0v3h5tfuye253mdttcshozxicj4kicagiemux/g8yni+ciagicagicagx/jkx9pjwazq+nkz1+mzybxev9w85kgjsw5ub0rctoa0otl9x+bss7xetppqoc6qmtzlqqos0ru49sf409a2nlj2wazq+lxe0rpx6bpjo6zl+dluw7+49sf4tcs089chtrzkxzfnqqgjsw5ub0rcideumc54soaxvr+qyrzs/cjr0bnl9dkzo6y8tmo/upbss7xetppqob/j0ttu2r2ose3ksc2ouf2yzsr9a2v5x2jsb2nrx3npemxj6nbdzqoys6gineuhojhlo6zs8rtlw7+49sf4tttt2tkztctk/cg/vs3oqjuxmqgimju2oaixmjaho0lubm9eqiaxljiuwldmsb7qwtt2ss7k/wlubm9kyl9wywdlx3npemw9q8ssym/ss7xetppqocno1spoqjrloai4s6ostavkx9kz1tc1xmr9vt2yu8rh0bnl9aos1elkx8f41tc1xmr9wb/nrnh5zqoyntahojeyokgj0ru+5luwo6yyu8lbwta1xltz0khu9co0ses7r6osx/i1xltz0kgyu7hkmu2ho7wrysft0nxi0fnsu7j2zsrm4qo61nq/qsb0tsdborhtv9w85nauuvojrls0vai1xlhtxkziz7tz0khkxzk2s6osx/jw0mrhnjs49sgs0pi1xnkzo6y0tl2otcsx7b/vvottprjdyscxtblftttrvao/1elkx9lyzqru2so/upa2zrxev6rkvmqxo6zpynpdmzk49tkztppqobxey+ngrnkzkgzyywdtzw50cibwywdlkcc0sao05sr9vt2jrntayrntw83q1elqqdkz1q6687lfysc2nlj2wazq+lxe0ro1xmnqx+uho9xi0fnx9srhtttt2tk70knqobhtu/lv33vuzg/v4sdgtcs2zqosv8ns1ntav6rkvmqxyerh673pydm1xl/vvosjrl3ayqg0xcxmyn3bv7xev6rp+qgjpgjypgogicagrc7sszxicj4kicagicagicdss8rhsw5ub0rctmxfzlncwo21xnfu0kg1pc67oapermjptppqoc6qmtzlo6y/ydluzai5/wlubm9kyl9wywdlx3npemw9q9kztcs089chyejww86qneuhojhloaixnkujrntyy/nt0lht1tdss7xetppqoba8zqrj6nbdjimymdu0mdujrlk7v8ns1lbuxutu2bto0n64xkgjs/23x82ouf1texnxbgr1bxc1vmjrus21vlp2stnx98c0svrj+tdctcs/4qgjs6o8+7xe0ro1xmdg0m3t0drk/b7d0rmoqi10cmvlie5vzgupoaj1bmrv0rmodw5vzcbmb2cgugfnzsmhos+1zbpssyhtexn0zw0gugfnzsmhosrczvhk/b7d0rmovhjhbnnhy3rpb24gc3lzdgvtifbhz2upoaky5cjru7qz5b/vz9db0lht0rmosw5zzxj0iej1zmzlcibgcmvliexpc3qpoalotng5y/w1xlb+vfjwxrtztttp89kzkfvuy29tchjlc3nlzaogqkxpqibqywdlkagi0bnl9bxetv69+nbgtttp89kzkgnvbxbyzxnzzwqgqkxpqibqywdlktxicj4kicagieuu0na8yni+ciagicagicagsw5ub0rctoa0otl9x+bkx8pmz/lq0lxekhjvdy1vcmllbnrlzcmjrnkyvs3kx8u1yv2+3crhsltq0l340nc05rfftcsho8o/upbss7tmt8w1xndqvmfcvnkyysft0noy0ns2qnlltcsjrnfutuduy9dqtoa3xte2sy8yltiwmndqtcs8x8k8o6y8tdc5otlq0lzhwryhozwvcd4kcjxwpjmusw5ub0rc0nc8x8k8jimynjy4ndvkvtxicj4kicagielubm9eqrtmtkls/cfmtcs8x8k8ysfs1ndqtctqzsq9toa0orxeo6zv4r7nse3d99kz1tcxo7tm18wx7dbq0rvq0ndqtctk/b7doapg5mdg0m3t0fjfrfvorefovkgiienptvbbq1shoknptvbsrvntoajewu5btuldy8tw1qgjv8ns1m2ouf1zag93icb0ywjszsbzdgf0dxm7wlsy6b+0tbhhsl/i1tddv9xfse21xmr9vt0mizi2njg0o8q9yofpws28ojxicj4kicagpgltzybzcmm9http://www.bitscn.com/uploadfile/collfiles/20141202/20141202092356171.jpg alt=\>
a.compact
在mysql 5.0中引入,其设计目标是高兴的存储数据。也就是一个页中存放的行数据越多,其性能越高。compact行记录的存放方式:
有图可知,compact行记录格式的首部是一个非null变长字段长度列表,并且其是按照列的顺序逆序放置的,其长度为:
若列的长度小于255个字节,用1字节表示;
若大于255个字节,用2字节表示。
变长字段之后的第二个部分是null标志位,该位置指示了该行数据中是否有null值,有这用1表示。该部分占1个字节。接下来就是占用5个字节的记录头信息(record header),每位的含义如下图:
最后的部分就是实际存储每列的数据。注意null不占该部分的任何空间,也就是说null除了占有null标志位,实际存储不占任何空间。每行除了用户定义的列外,还有2个隐藏列(事务id列(6字节)和回滚指针列(7字节))。若innodb表没有定义主键,还会增加一个6字节的rowid列。不管是char类型还是varchar类型,在compact格式下null值都不占用任何存储空间。
compact行格式特点:
每个也记录都有5字节长度域,用于指向下一个连续的页,并且可用于实现行锁
有个变长域,存储页中有多少可能为null的字段数,长度为 ceiling(n/8)字节,同时也需要用1~2字节存储边长字段所需长度
所有非null的变长字段,用1~2字节存储其长度信息
行记录头部域之后,紧跟着就是所有非null的字段
utf8字符集的char(n)字段,优先删除末尾空格,尝试用n字节存储,并且再预留n个字节用于后续数据更新,避免产生碎片
b.redundant
redundant是mysql 5.0版本之前innodb的行记录存储方式。如图:
redundant行记录格式的首部是一个字段长度偏移列表,同样是按照列的顺序逆序放置的。若列的长度小于255字节,用1字节表示;若大于255字节,用2字节表示。第二个部分记录头信息(record header)。如下图:
最后的部分就是时间存储的每个列的数据。
redundant行格式特点:
每个页包含6字节rowid,用于指向下一个连续的页,并且可用于实现行锁
聚集索引中包含所有字段,并且包含额外的6字节trx_id,和7字节roll_ptr
如果没显式主键,则使用隐含的6字节rowid作为主键
行记录中存储指向全部字段的指针,字段长度小于128字节时,该指针占用1字节,否则需要2字节
类似char的定长类型字段,也采用固定宽度存储,并且不删除末尾的空格
类似varchar变长类型字段中null不会占用实际存储空间,而char定长类型字段中,null则占用相应的字节数
c.行溢出数据
innodb存储引擎可以将一条记录中的某些数据存储在正在的数据页之外。一般认为blob、lob这类的大对象类型的存储会把数据存放在数据页面之外。这个理解有点偏差,blob等可以不将数据房子溢出页面,而且即使是varchar列数据类型依然有可能被存放为行溢出数据。这个主要取决于实际存放的数据。
d.compress和dynamic
innodb 1.0.x版本引入了新的文件格式(file format),以前支持的compact和redundant格式称为antelope文件格式,而新的文件格式称为barracuda文件格式。其barracuda包括两种新的行记录格式:compressd和dynamic。新的两种记录格式对呀存放在blob中的数据采用完全的行溢出的方式,在数据页中只存放20个字节的指针,时间的数据存放在off page中。而之前的compact和redundant会存放钱768个前缀字节
compact与redundant的区别
compact相比redundant约可节省20%左右, compress相比compact约可节省50%左右,但会导致cpu消耗增加,tps可能只有原来的10%
类似char的定长类型,也采用固定宽度存储,并且不删除末尾的空格(varchar则会删除空格)
所有辅助索引存储了那些在主键定义中存在,但不在辅助索引中存在字段(提高辅助索引检索效率)
dynamic、compressed格式中,长字段只存储20字节,其余全部off-page(实际长度40字节以内的,则不会发生off-page,哪怕是text/blob)
未完待续。。。