算法可视化网站 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并没有排好序
网友评论