美文网首页
深入理解Mysql索引底层数据结构与算法

深入理解Mysql索引底层数据结构与算法

作者: 小强的进阶之路 | 来源:发表于2019-08-20 23:08 被阅读0次

    索引是帮助MySQL高效获取数据的排好序的数据结构

    索引数据结构对比

    二叉树

    左边子节点的数据小于父节点数据,右边子节点的数据大于父节点数据。
    如果col2是索引,查找索引为89的行元素,那么只需要查找两次,就可以获取到行元素所在的磁盘指针地址。

    二叉树索引示意图

    如果col1是索引,查找索引为6的行元素,那么需要查找六次,就可以获取到行元素所在的磁盘指针地址,即得到了该索引为6的行元素。因此二叉树不适合存储单边增长的序列字段,近乎全表扫描获取数据。

    红黑树

    本质二叉树,属于二叉平衡树,jdk1.8 hashmap的底层实现;
    存储大数据量,树的高度不可控, 数量越大,树的高度越高;
    500w行数据,2的n次方=500w数据量, n是树的高度,也就是查询次数;

    hash表

    通过散列可以快速获取磁盘文件指针,对于指定索引查找文件非常快,但是对于范围查找没法支持。

    B树

    本质是多路二叉树;
    叶节点具有相同的深度,叶节点的指针为空;
    所有索引元素不重复;
    节点中数据索引从左到右依次递增的;

    B树索引示意图
    B+树(B树的变种)

    非叶子节点不存储数据,只存储索引(冗余)和指针,可以放更多的索引,树高降低 ;
    叶子节点包含所有索引字段;
    叶子节点比b树增加了指针连接;
    叶子节点有双向指针链接(首尾子节点还通过指针连接),提高区间访问的性能,范围查找;

    B+树索引示意图

    为什么mysql页文件默认16K?

    MySQL每个B+树节点最大存储容量:16KB (指针+数据+索引)。假设我们一行数据大小为1K,那么一页就能存16条数据,也就是一个叶子节点能存16条数据;再看非叶子节点,假设主键ID为bigint类型,那么长度为8B,指针大小在Innodb源码中为6B,一共就是14B,那么一页里就可以存储16K/14=1170个(主键+指针)
    那么一颗高度为2的B+树能存储的数据为:117016=18720条,一颗高度为3的B+树能存储的数据为:11701170*16=21902400(千万级条)

    show global status like `Innodb_page_size`
    

    因此,B+树存储大数据量的表也可以非常高效的获取数据,MySQL使用B+树作为索引的数据结构。

    存储引擎

    存储引擎最终作用于:表 ,不是数据库
    在mysql的安装的根目录下,有一个data目录,里面存放的是所有表的数据。

    • MyISAM:
      MyISAM索引文件和数据文件是分离的(非聚集或稀疏);
      主键索引和辅助主键索引存储类似;

    frm文件:存储这张表的表结构
    MYD文件:存储这张表的所有数据行
    MYI文件:存储这张表的索引字段

    MyISAM存储引擎底层结构
    • InnoDB(聚集):

    表数据文件本身是按照B+tree组织的一个索引结构文件
    frm文件:存储这张表的表结构
    ibd文件:存储这张表的所有数据行和索引字段
    聚集(聚簇)索引----叶节点包含完整数据记录

    InnoDB存储引擎底层结构

    为什么InnoDB表必须有主键,并且推荐使用整型的自增主键?

    • 首先,为了满足MySQL的索引数据结构B+树的特性,必须要有索引作为主键,可以有效提高查询效率,因此InnoDB必须要有主键。如果不手动指定主键,InnoDB会从插入的数据中找出不重复的一列作为主键索引,如果没找到不重复的一列,InnoDB会在后台增加一列rowId做为主键索引。
    • 其次,索引的数据类型是整型,一方面整型占有的磁盘空间或内存空间相比字符串更少,另一方面整型比较比字符串比较更快速,字符串比较是先转换为ASCII码,然后再比较的。
    • 最后,B+树本质是多路多叉树,如果主键索引不是自增的,那么后续插入的索引就会引起B+树的其他节点的分裂和重新平衡,影响数据插入的效率,如果是自增主键,只用在尾节点做增加就可以。

    为什么非主键索引结构叶子节点存储的是主键值?

    • 主键索引和非主键索引维护各自的B+树结构,当插入的数据的时候,由于数据只有一份,通过非主键索引获取到主键值,然后再去主键索引的B+树数据结构中找到对应的行数据,节省了内存空间;
    • 如果非主键索引的叶子节点也存储一份数据,如果通过非主键索引插入数据,那么要向主键索引对应的行数据进行同步,那么会带来数据一致性问题。可以通过事务的方式解决,我们都知道使用事务后,就会对性能有所消耗。

    联合索引

    • 联合索引的底层存储结构长什么样?

      定义联合索引(员工级别,员工姓名,员工出生年月),将联合索引按照索引顺序放入节点中,新插入节点时,先按照联合索引中的员工级别比较,如果相同会按照是员工姓名比较,如果员工级别和员工姓名都相同 最后是员工的出生年月比较。可以从图中从上到下,从左到右看,第一个B+树的节点 是通过联合索引的员工级别比较的,第二个节点是 员工级别相同,会按照员工姓名比较,第三个节点是 员工级别和员工姓名都相同,会按照员工出生年月比较。

    联合索引示意图

    还没关注我的公众号?

    • 扫文末二维码关注公众号【小强的进阶之路】可领取如下:
    • 学习资料: 1T视频教程:涵盖Javaweb前后端教学视频、机器学习/人工智能教学视频、Linux系统教程视频、雅思考试视频教程;
    • 100多本书:包含C/C++、Java、Python三门编程语言的经典必看图书、LeetCode题解大全;
    • 软件工具:几乎包括你在编程道路上的可能会用到的大部分软件;
    • 项目源码:20个JavaWeb项目源码。


      小强的进阶之路二维码

    相关文章

      网友评论

          本文标题:深入理解Mysql索引底层数据结构与算法

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