MySQL索引原理
- 1、Innodb中的B+树是怎么产生的呢? 背景
- 1.1、mysql索引使用B+树,为什么?
- 1.2、主键索引图示
- 1.3、mysql最好使用自增ID:为什么呢?
- 1.4、高度为3的B+树能存多少条数据?
- a、假设2层
- b、假设3层
- 2、索引采用什么数据结构?
- 3、为什么不用哈希表进行数据存储
- 4、B+ 树特点
- 5、回表、索引覆盖、最左匹配的区别
- 6、内存与磁盘交互问题
1、Innodb中的B+树是怎么产生的呢? 背景
类似链表存储
mysql数据存在磁盘还是内存?磁盘
mysql的索引数据存储在那?磁盘
存在内存,一旦断电,索引需要重新重建
1.1、mysql索引使用B+树,为什么?
mysql的数据存储在磁盘,mysql的索引数据也存在磁盘——》这里就涉及到了磁盘的交互过程——》通过IO交互:为了减少资源消耗:减少io量,减少io次数
当数据量非常大的时候,没办法一次加载到内存中——》采用分块读取——》分而治之——》磁盘预读,在内存和磁盘之间交互有一个最基本的的逻辑单位,称为页,也叫做datapage,datapage的大小跟操作系统相关,一般是4kb或者8kb,我们在进行数据读取的时候一般选择页的整数倍进行读取。
innodb存储引擎每次读取16kb
1.2、主键索引图示
一页有16kb,每一页包含页目录、用户数据区域、指针。
1.3、mysql最好使用自增ID:为什么呢?
当使用索引列进行数据查询的时候,最终会到主键索引树中查询对应的数据行进行返回。
mysql中一页有16kb的数据,假设我插入了4条数据,一页占满了;
当我插入第5条数据,如果一页满了会新增一页,
但是会出现新插入的数据加入到那一页?
如果不是自增列的话,会修改之前已经满的页,影响性能。
指针指向
当第2页中的数据满了会新增第3页…,依次类推
当插入a=60000时,在磁盘中,会从第一页开始遍历链表,速度太慢了。怎么优化?
在这些页的上层增加1页,只存储组件和指针,其中int类型占4个字节 + 指针占6个字节 = 10个字节。
整页16kb/10字节=(1638页)存多少页
当a=60000的时候,可以从第一层的数据获得具体的索引范围,接着向下取数据。
效率立刻提升。
类似于下方的图示
1.4、高度为3的B+树能存多少条数据?
a、假设2层
假设:数据表中每一条记录为1kb,
一页里面能存多少条记录:16kb/1kb
一共1638页,
存1638*(16kb/1kb)= 26208
b、假设3层
一般情况下,3层的B+树足以支撑千万级别的数据量存储。
2、索引采用什么数据结构?
数据结构——》哈希表、一堆树——》B+树
3、为什么不用哈希表进行数据存储
1、哈希冲突和哈希碰撞问题,当哈希算法有问题的时候会造成大量的哈希碰撞问题,导致数据聚集。
2、哈希表是散列表,数据是无序的,当需要进行范围查询的时候只能挨个对比,效率比较低。
memory存储引擎使用的是哈希索引
innodb存储引支持自适应哈希
4、B+ 树特点
B+Tree是在BTree的基础之上做的一种优化,变化如下:
1、B+Tree每个节点可以包含更多的节点,这个做的原因有两个,
- 第一个原因是为了降低树的高度。
- 第二个原因是将数据范围变为多个区间,区间越多,数据检索越快。
2、非叶子节点存储key,叶子节点存储key和数据。
3、叶子节点两两指针相互连接(符合磁盘的预读特性),顺序查询性能更高。
5、回表、索引覆盖、最左匹配的区别
例如:
select * from 表名 where time=“zhangsan”——》回表
select id,name from 表名 where time=“zhangsan”——》索引覆盖
6、内存与磁盘交互问题
update数据时:
1、判断更新的数据是否在内存中,如果在内存中直接更新数据
2、如果不在内存中,需要把磁盘的数据加载到内存中
3、去修改内存的数据
4、再把内存中的数据溢写到磁盘中。
内存往磁盘写的过程中可能出现没写完就断掉了,导致数据丢失。
随机读写:
磁盘寻址找到数据需要消耗时间
顺序读写:
append,写入日志redlog
举例:
餐馆,记账本——》找到个人账单——》加上10元
餐馆,小黑本——》记录消费的金额——》不忙的的时候再把信息挪到记账本中。