美文网首页
mysql-存储引擎

mysql-存储引擎

作者: zoooooyyyy | 来源:发表于2020-08-21 22:08 被阅读0次

    说到mysql,首先得先看看mysql支持的存储引擎。mysql支持的引擎很多,以下就常用的几种进行以下介绍。

    image.png

    InnoDB

    https://zhuanlan.zhihu.com/p/103582178

    InnoDB是mysql的默认存储引擎,使用InnoDB存储时,会把表的定义存储在.frm文件中,把数据和索引文件存在.idb文件中。5.7以后引入General Tablespace,可以把多个表放到一个文件里

    表空间
    innodb逻辑存储结构

    从图上可以看出来,表数据都存储在表空间(Tablespace)中,表空间中又包含段(Segment)、区(Extent)、页(Page)组成。

    表空间存在两类
    (1)默认情况,数据存储使用公共的表空间ibdate
    (2)设置了参数innodb_file_per_table,每个表可以存放在单独的表空间中。当然,也不是所有的数据都支持单独存储,只有数据、索引、插入缓冲Bitmap页可以存放在单据的表空间中,会滚信息,插入缓冲索引页,系统事务信息,二次写缓存还是存储在公共的表空间中

    文件管理页
    文件管理页结构

    默认一个extent(1MB)管理64个物理连续的page(16k)。如果page大小小于16k,那么会增加实际的page数量,保持extent大小为1MB;相应的,如果page的大小大于16k,则保持page的数量依旧为64个,extent的大小会大于1MB。

    文件管理页的类型是FSP_HDR/XDES(extent descriptor),用于分配、管理extent和page。
    FSP_HDR/XDES大小是16k,所以能管理的extent数量是有限的。一般一个FSP_HDR能够管理256个extent(一个extent描述占40字节),表空间文件越大,所需要的的FSP_HDR/XDES页就越多。
    FSP_HDR/XDES页内部存储的XDES Entry管理extent的状态,相同状态(一共四种状态)的extent收尾相接,组成了一个双向链表。

    extent的状态

    • FREE(空)
    • FREE_FRAG(至少一个被占用)
    • FULL_FRAG(满)
    • 归某个segment管理的信息

    FSP_HDR和XDES的唯一区别是page 0 的FSP_HDR中包含FSP Header的值,里面存储了四个状态链表(FSP_FREE、FREE_FRAG、FULL_FRAG、FSEG)的头尾数据

    INODE页
    inode页结构

    INODE页位于文件的page2上,用于管理segment,每个inode entry负责一个segment。
    mysql的数据是按照B+树聚簇索引组织数据的,每个B+数会使用两个segment来管理page,分别是叶子节点segment和非叶子节点segment,这两个segment的inode entry地址记录在B+数的root page中的FSEG_HEADER中,root page又被分配在非叶子segment的第一个碎片页上。

    每个segment由32个碎片页(fragment array),FSEG_FREE、FSEG_NOT_FULL、FSEG_FULL组成,这些信息记录在Inode entry里,可以简单理解为Inode就是segment元信息的载体。FREE、NOT_FULL、FULL三个FLST_BASE_NODE对象和FSP_HDR/XDES页里面的FSP_FREE、FREE_FRAG、FULL_FRAG、FSEG概念类似。这些链表被InnoDB使用,用于高效的管理页分配和回收。

    碎片页用于优化小表的空间分配。先从全局的碎片空间分配page,当碎片页填满(32)后,每次分配一个完整的extent(1M),如果表大于32M,则一次分配4个extent

    INDEX数据索引页
    B+树聚簇索引

    索引用于快速定位数据。对innodb来说,主键和非主键都是索引,一切数据都存储在INDEX索引页中,索引=数据。

    索引可以有多种存储结构,具体如下

    • 哈希索引(hash):按key查询性能好,可是需要解决hash碰撞问题,且区间查询不友好
    • 有序数组(sorted array):修改不便,只使用与静态存储引擎
    • 二叉查找树(binary search tree):更新、查询复杂度都为O(logN)。二叉查找树最大的问题就在于随机IO,所以引入了N叉树
    • N叉树:减少了树的高度和随机IO的次数,例如当N=1200,树的高度可以控制在4层,管理1200^3=17亿行。一般根节点在内存,所以最多3次磁盘IO。不仅减少了随机IO次数还保证了查询的稳定性,所以说这种数据结构是一种scales nicely的解决方案。
    • 新模型:LSM-tree、跳表skiplist等

    聚簇索引和非聚簇索引

    image.png

    一张MySQL表只有一个聚簇索引,聚簇索引可以看做主键,如果建表没有指定主键默认采用第一个NOT NULL UNIQUE INDEX当主键,否则默认6字节的ROW ID做主键。总之InnoDB必须有一个primary key。

    使用B+树聚簇索引(B+ tree clustered index)的好处在于:

    1. 数据和索引顺序一致,充分利用磁盘顺序IO性能普遍高于随机IO的特性。
    2. 对于局部性查询也会大有裨益。
    3. 采用B+树,叶子节点(leaf node)存储数据,非叶子节点(non-leaf node)只是索引,这样非叶子节点就会足够的小,因此数据很“热”,便于更好的缓存。
    4. 对于覆盖索引,可以直接利用叶子节点的主键值。

    mysql的二级索引可以看做在非聚簇索引。它的结构也是一颗B+树,叶子节点是指向聚簇索引的主键(可以看成行指针),查询具体数据的时候需要回表

    索引页结构

    索引页包含主键、二级索引、行和列。B+树的每个节点都是一个INDEX索引页。
    聚簇索引:非叶子节点包含主键和child page number,叶子节点包含主键和具体的行
    二级索引:非叶子节点包含二级索引和child page numbe,叶子节点包含二级索引和主键值

    行由列组成,各种列类型结构encoding编码后才组成了一行

    具体模型
    image.png

    微观上把每个页节点内部展开成由infimum和supermum连接起来的有序单链表,结构如下。每层的页通过Fil Header相互连接。

    列类型

    row format可通过innodb_default_row_format参数指定,也可以在建表的时候指定。

    CREATE TABLE tab (
       id INT,
       str VARCHAR(50)
    ) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
    

    MyISAM

    使用该存储引擎时,数据会在磁盘上存储成三个文件

    • frm:存储表的定义
    • MDY:存储表的具体数据记录
    • MYI :存储索引

    frm和MYI允许存放在不同的目录下,MYI文件仅用于索引的存储(仅存储记录所在页的指针,不存储具体的数据),索引的结构为B+树

    进行查询操作时,会先根据索引查找到记录页,再把页加载进内存进行具体记录的查找

    MEMORY

    数据存储在内存中。为了提高数据的访问速度,每个表管理一个磁盘文件(frm)

    相关文章

      网友评论

          本文标题:mysql-存储引擎

          本文链接:https://www.haomeiwen.com/subject/nsypjktx.html