Mysql索引学习笔记

索引为什么用B+树

  • 二叉树会出现单点增长的情况,严重影响查询效率


  • 红黑树 虽然有自动平衡的特点,但是随着数据量的增长,树的高度不可控,也会影响查询效率
  • 用hash也可以但是hash不能查找排序 只是查找单个值的时候快

Btree树



Btree树每个节点可以存储多个数据,从而控制了树的高度,可以通过度来控制每个结点存储数据的个数

思考: 那么是不是设置度越大磁盘一次IO既可以加载越多的数据,其实不然,磁盘每次IO读取数据的大小是有限制的,索引度的大小跟CPU一次IO加载数据的大小有关,由于B-tree树中每个数据中存储着该行数据,所以当每行数据比较大的时候,每个节点也存储不了多少数据,没了解决这个问题引入B+树结构

B+树




如上图,是一颗b+树,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),如磁盘块1包含数据项17和35,包含指针P1、P2、P3,P1表示小于17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块。真实的数据存在于叶子节点即3、5、9、10、13、15、28、29、36、60、75、79、90、99。非叶子节点只不存储真实的数据,只存储指引搜索方向的数据项,如17、35并不真实存在于数据表中。

b+树的查找过程

如图所示,如果要查找数据项29,那么首先会把磁盘块1由磁盘加载到内存,此时发生一次IO,在内存中用二分查找确定29在17和35之间,锁定磁盘块1的P2指针,内存时间因为非常短(相比磁盘的IO)可以忽略不计,通过磁盘块1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存,发生第二次IO,29在26和30之间,锁定磁盘块3的P2指针,通过指针加载磁盘块8到内存,发生第三次IO,同时内存中做二分查找找到29,结束查询,总计三次IO。真实的情况是,3层的b+树可以表示上百万的数据,如果上百万的数据查找只需要三次IO,性能提高将是巨大的,如果没有索引,每个数据项都要发生一次IO,那么总共需要百万次的IO,显然成本非常非常高。

b+树性质

局部性原则,磁盘预读,一次IO中认为相邻的一些数据也会在近期被访问。
考虑到磁盘IO是非常高昂的操作,计算机操作系统做了一些优化,当一次IO时,不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓冲区内,因为局部预读性原理告诉我们,当计算机访问一个地址的数据的时候,与其相邻的数据也会很快被访问到。每一次IO读取的数据我们称之为一页(page)。具体一页有多大数据跟操作系统有关,一般为4k或8k,也就是我们读取一页内的数据时候,实际上才发生了一次IO,这个理论对于索引的数据结构设计非常有帮助。


注意:数据路引擎是表级别的

MyISAM引擎


MyIsam中索引文件和数据文件是分离的称作非聚集索引
.frm是存储的是表结构
.MYD MYISAM数据文件
.MYI MYISAM的索引文件



可以看出Myisam引擎索引存储的不是真是数据,而是数据的引用地址

InnoDB引擎


可以看出只有两个文件



InnoDB通过主键将整行数据关联(数据文件与索引文件是一体的),称作聚集索引
所以InnoDB数据库表是必须要有主键的

  • 为什么InnoDB推荐使用整型自增主键?
  1. 整型相比其他类型比较时速度更快
  2. 插入数据时直接放到节点数据的右侧,不会分裂,速度更快
  • 如上图为什么InnoDB中非主键索引存储的是主键?
  1. 为了节省空间
  2. 避免插入数据时每个索引都要维护整行数据,造成数据不一致问题

InnoDB支持事务支持行锁

联合索引底层怎么存储的?

索引的最左原则(左前缀原则),如(c1,c2,c3,c4....cN)的联合索引,where 条件按照索引建立的字段顺序来使用(不代表and条件必须按照顺序来写),如果中间某列没有条件,或使用like会导致后面的列不能使用索引。

索引也能用于分组和排序,分组要先排序,在计算平均值等等。所以在分组和排序中,如果字段顺序可以按照索引的字段顺序,即可利用索引的有序特性。

MySQL索引学习

https://www.cnblogs.com/bypp/p/7755307.html

MySql Explain学习

https://www.cnblogs.com/yycc/p/7338894.html

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容