mysql索引原理及多版本控制(MVCC)原理

文章详细介绍了几种常用的数据结构在数据库索引中的应用,重点对比了B树和B+树的差异,包括B+树如何优化查询效率和存储结构。同时,提到了MySQL中索引的实现,如聚集索引和非聚集索引的工作原理,以及何时使用回表查询。此外,文章还讨论了哈希表在特定查询场景下的效率问题,并列举了可能导致索引失效的情况。最后,简述了多版本并发控制(MVCC)在数据库隔离级别中的作用。
摘要由CSDN通过智能技术生成

索引常用的数据结构:

         二叉树:取第一个值作为根节点,取第二个值和第一个值比较,小的放左边、大的放右边,如果是顺序排列的数字,则全部放在右边就像链表一样了
        红黑树:在二叉树上做了优化,连续出现两个都是大于或小于的数,则会自旋一次,如5后面插入6、7,插入后自旋一次6的左边是5、右边是7
        Hash表:每个值都有一个hash值,hash值索引记录这个hash值和数据的对应关系,对于 =、in等查询效率很高,对于范围查询如 大于、小于、like则很慢,只能全表扫描
            B-Tree:根节点不再是一个节点,而是多个节点的集合,这样可以较少树的深度
            B+Tree(B-Tree的变种):
                   非叶子节点不存储data,只存储索引(冗余)
                   叶子节点包含所有的索引字段(数据库表数据)
                   叶子节点用指针连接,提高区间访问的性能

B+Tree和B Tree:

        1、由于索引文件很大并存储在磁盘上,B+Tree的非叶子节点存储的都是索引关键字,单个页可以存储更多的关键字;B Tree非叶子节点也存储数据、单页存储的索引关键字少。所以B+Tree需要读取索引关键字的次数会少一些,减少IO提升效率;

        2、B+树叶子结点之间用链表有序连接,所以扫描全部数据只需扫描一遍叶子结点,利于扫库和范围查询;B树由于非叶子结点也存数据,所以只能通过中序遍历按序来扫。也就是说,对于范围查询和有序遍历而言,B+树的效率更高。

    B+Tree 和 B Tree的结构:       

Mysql的索引结构:

    B+Tree 和 hash值两种方式,现在索引基本上都是使用B+Tree(也是默认的),hash也只在某些特殊场景下使用;


        1、B+Tree索引:

            (1)、索引都是有序的,;
            (2)、一张表中只有一个聚集索引:通过主键(没有主键的话数据库会自动生成一个rowid)进行排序的索引;
            (3)、其他的非聚集索引的叶子节点存储的是主键的值,查询的时候首先在这个非聚集索引中定位到主键,然后通过主键在聚集索引中找到对应数据,这种情况叫做回表查询。如果非聚集索引中筛选出的主键比较多,此时回表查询的效率会比较低,mysql的优化器会选择全表扫描而不走索引,所以不是走了索引就表示效率高;
            (4)、如果查询的条件及结果都在一个非聚集索引中,此时不需要回表查询,这种情况叫做覆盖索引查询,效率比较高;

    非聚集索引的数据结构,以联合索引为例,最下面的数据为主键:

        (5)、B+树的深度:数据的存储是按照页来存储的,每一页的大小默认是16kb

               1、对于非叶子节点每一层级能容纳多少个节点和索引的大小有关系,如果索引列是int类型(范围从-2^31到2^31-1,大约正负20亿)占用4个字节,每个节点有一个指针是6个字节(固定大小),那么一个节点占用10个字节,则非叶子节点一层的节点数是 16*1024/10 = 1638 个,如果索引列是bigint占用8个字节,则非叶子节点一层的节点数是 16*1024/14 = 1170个;

               2、聚集索引的叶子节点一页能存储多少条数据跟每一行的数据大小有关,假如叶子节点一行占用1kb,则一页能存储16行数据;

               3、B+树的深度计算,按bigint、一行1kb计算,2层结构能存储1170*16 = 18720条数据,三层结构能存储 1170*1170*16 = 21902400 也就是大约2000万条数据;

         (6)、索引字段的长度:

                 1、不同的编码格式每个字符占用的字节数也是不一样的,我这里是utf8mb3,每个字符占三个字节,另外不同版本的mysql支持的索引长度是不一样的,我这里是8.0.29索引长度不能超过1000

                 2、查看索引的长度可以通过explain查看执行计划中的key_len,如果是复合索引在每个索引值都匹配了查询条件的情况下key_len即为索引的长度

                 3、如果列可以为空,则索引长度加1,如果是可变字段长度如varchar则索引长度加2,可参考:SQL优化(五)索引长度_sql索引字段过长_万里归来少年心的博客-CSDN博客

    2、hash值索引:

          每个值都有一个hash值,hash值索引记录这个hash值和数据的对应关系,对于 =、in等查询效率很高,对于范围查询如 大于、小于、like则很慢,只能全表扫描;

索引失效的三种情况:

        1、查询条件导致索引失效

             1)、like前面有 %;

             2)、对索引字段进行了类型转换:date(clo1)='2022-01-01',或给字符串是varchar类型的列传入数字类型条件;

            3)、在索引上使用了函数 如 left(col1,2)='zs' 或 使用计算的表达式 如col1+col2 > 100;

            4)、创建索引时对索引列使用了函数,必须使用这个函数作来匹配条件才有效

                   如: create index a_index on table1(to_char(column1));

            5)、不等于、not in、not exists 也会是索引失效;

        2、不满足最左匹配原则

                复合索引的左边字段没有使用索引,右边字段的索引都不能用;

        3、回表查询时需要传给 聚集索引 的值太多,数据库解释器会觉得全表扫描更快

索引合并:

        一个表的多个查询条件都有索引,查询的时候用到了两个或多个索引,叫做索引合并;

        索引合并一般不会出现,只有查询条件是全词匹配或者其中一个条件是id、并且每个索引查询的数据都比较多但是交集后数据比较少的情况下才会出现;

        参考:Mysql——》index merge 索引合并_mysql index merge-CSDN博客      

 多版本控制机制(MVCC):

          数据库隔离级别中读已提交、可重复读 使用了MVCC;

         读已提交 和 可重复读的区别是生成read-view(记录库中未提交的事物ID 及 已提交的最大事物ID)的方式不一样,读已提交 是每次查询都生成一次,可重复读是在一个事物中第一次查询就生成一次、后面不再生成;

        MVCC的实现原理:

               1、数据库中的事物id是递增的;

               2、对数据库表的每一次操作都会记录undolog;

               3、根据读已提交 和 可重复读 生成的read-view从undolog获取对应的数据;                 

课件相关资料:链接:https://pan.baidu.com/s/1peEnotKgJ_tjFbY4escZjg?pwd=f67n 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值