美文网首页
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