美文网首页
1:MySQL索引底层数据结构

1:MySQL索引底层数据结构

作者: _River_ | 来源:发表于2021-04-22 15:25 被阅读0次
    算法可视化网站  https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
    

    索引引擎结构(重要 重要 重要 )(先有印象):
    InnoDB索引引擎   索引可以存储  data数据本身
    MyISAM索引引擎  索引可以存储  data的地址
    
    0:总览
    什么是索引:
    索引      是帮助MySQL高效获取数据   的排好序的数据结构
    
    索引是排好序的数据结构(哪怕该索引插入进去的时候是无序的,它也会进行索引维护来排序)
    
    数据的查询效率 看的是进行IO的次数
    树越高 需要进行 IO次数 也就越多
    
    索引数据结构
    1:二叉树(无法解决平衡 无法解决树高)
    2:红黑树(解决局部平衡 无法解决树高)
    3:B-Tree (无法极致的解决树高 无法极致的解决范围查找)
    4:B+Tree (MySQL索引使用数据结构  支持等值查找 支持范围查找)
    

    5:Hash表(仅限于 等值查找  不支持范围查找)
    
    1:二叉树(Binary Search Tree)
     数据无序:
    select * from table where Col2=89 
    1:如果没有索引 全表扫描磁盘 需要查找6次
    2:如果有二叉树索引  需要查找2次
    
    数据递增:
    select * from table  where Col1 = 6
    1:如果没有索引 全表扫描磁盘 需要查找6次
    2:如果有二叉树索引 也是需要查找6次    
    这也就是为什么MySQL当数据是递增(自增的主键)的时候,
    为什么不选择二叉树的原因。
    
    2:红黑树(Red/Black Tree)
    1:根节点是黑色的
    2:其他节点是红色或黑色
    3:每个红色节点必须有两个黑色的子节点
    (从每个叶子到根的所有路径上不能有两个连续的红色节点)
    4:从任一节点到其每个叶子的所有简单路径
        都包含相同数目的黑色节点
    
    遵循如上规则的二叉树被称为红黑树,但是为什么要定义成如上规则呢?
    事实上,如上所有的规则都只想做一件事,让二叉树尽可能的平衡。
    
    当数据量大的时候 树会变得特别特别高
    从根节点到对应的叶子节点的查询效率非常慢
    
    最根本的问题:树的高度
    
    3:B-Tree
    1:节点中的数据索引从左到右递增排列
    2:叶节点具有相同的深度,叶节点的指针为空    
    

    注意:所有索引元素不重复
    
    特点:非叶子节点可以存储data(真正的数据)
    
    设置每一个索引页最多存储4个索引子页(注意索引元素不重复)
    
    4:B+Tree(B-Tree的变种)
    1:节点中的数据索引从左到右递增排列
    2:叶节点具有相同的深度,叶节点的指针为空  
    

    注意:索引元素会重复
    
    特点    
        1:非叶子节点不存储data,只存储索引(冗余),可以放更多的索引
        2:叶子节点包含所有索引字段
        3:叶子节点用指针连接,提高区间访问的性能
    
    设置每一个索引页最多存储4个索引子页(或数据)(注意索引元素可能重复)
    

    如何进行查找:比如查找30
    1:把根节点的索引数据页 加载到内存(慢)  使用折半查找(二分法)(快)
    2:查找到 15的索引数据页
    3:把15的索引数据页 加载到内存(慢)  使用折半查找(二分法)(快)
    4:查找到 20的索引数据页
        以此类推
    5:查找到30这个索引   然后使用这个索引去磁盘里面找数据(慢)
    
    查找索引所在索引页的位置    相对于    磁盘IO来说      可以忽略不计
    
    Mysql 的每一个索引页有多大:16KB(官方默认值  不建议修改) 
    SHOW GLOBAL STATUS LIKE 'INNODB_page_size'
    
    MYSQL索引的最大数据类型为bigint(8个字节)   索引指向地址的指针6个字节
    
    16KB 的索引页可以存储 16KB 除以14字节 = 1170     
    那么进行两次索引页的IO 
    就可以查找到 1 368 900 个索引
    
    最后还需要进行一次叶子节点索引页的IO    
    假设一个Data为1KB(后面提及)
    那么一个索引页可以存储 16个DATA
    
    那么三次IO一共可以查询:21 902 400(2千万条数据)
    
    注意:
        通过最后叶子节点的链表 实现 范围查询   (对比Hash 索引  后文会提及)
    
    5:Hash索引
    Hash
    对索引的key进行一次hash计算就可以定位出数据存储的位置
    很多时候Hash索引要比B+ 树索引更高效
    理想情况下一次就可以定位到数据存储的位置
    
    hash冲突问题(使用hash碰撞+链表结构 形成hash桶结构)
    
     但仅能满足 “=”,“IN”,不支持范围查询
     如:name>Alice  导致需要全表扫描
    
    6:MyISAM索引引擎 与 InnoDB索引引擎
    两者索引都是表级别的索引。(新增表的时候可以选择存储引擎)
    

    MyISAM索引文件和数据文件是分离的
    tableName_myisam.frm(表结构)
    tableName_myisam.MYI(索引文件)
    tableName_myisam.MYD(数据文件)
    
     索引和数据分开存储的 
    
    B+Tree索引下查询步骤:  
    
    select * from tableName where iCol1 = 30
    1:查询索引文件 tableName_myisam.MYI 查找 iCol1的索引
    2:查询方式按照上述 B+ 树的查找方式
    3:获取 iCol1 = 30 的 数据地址(OxF3)
    3:根据 数据地址(OxF3)  查询数据文件 tableName_myisam.MYD 的对应数据
    

    InnoDB索引实现
    tableName_innodb_lock.frm(表结构)
    tableName_innodb_lock.ibd(索引文件 和 数据文件)
    
     索引和数据存储在一起 
    
    表数据文件本身就是按B+Tree组织的一个索引结构文件
    
    为什么建议InnoDB表必须建主键,并且推荐使用整型的自增主键?
    这里面包含两个问题:1:要有主键 2:整型的主键 3:自增的主键
         1:如果不建立主键,表会默认进行每列遍历,如果哪一列的数据没有重复则取该列为主键 
             都有重复的话,则新增一个隐藏列。
         2:  索引页比对大小,整型是比较数字大小,字符串是比较每一个字母ASCLL码大小
               索引存储的空间,整型比字符串小。
         3:自增的主键,不需要经过索引页的复杂的重排。
    
    为什么非主键索引结构叶子节点存储的是主键值?(一致性和节省存储空间)
        其中又分 聚集索引 和 非聚集索引
        InnoDB的主键(有且唯一) 是聚集索引(主键索引) 叶节点包含了完整的数据记录(一整行数据 )
        InnoDB的其他索引  是非聚集索引(二级索引)  存储的是主键的位置 (回表操作)
    
    7:InnoDB索引引擎总结
    InnoDB索引引擎 (索引文件 和 数据文件 放在同 一个文件)
    B+Tree:
                主键索引(聚集索引) :存储该索引 对应的行的所有数据
                
                非主键索引(非聚集索引):存储主键索引的数据
                然后需要回表操作(查询主键Data  再查询其他数据信息)
    
    8:联合索引(排好序概念的深度理解):
    最左匹配原则:
    先看最左边的字段  
    
    Key  'idx_name_age_postion'  (`name ` , `age` ,`postion`) USING BTREE
    Explain select * from emplayees where name ='Bill' and  age =31 ;
    Explain select * from emplayees where  age =30 and position ='dev'  ;  (不走索引)
    Explain  select * from emplayees where  position ='manger'  ;   (不走索引)
    
    因为:索引必须排好序  如果不限制 name  那么在整张表里面age并没有排好序
    

    相关文章

      网友评论

          本文标题:1:MySQL索引底层数据结构

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