一.MySql的实际存储位置
了解B+树前,我们先要知道MySql 的实际存储位置在哪?
不管是在个人电脑上使用本机MySql或者在互联网上把信息存在服务器上,其实它们最终的存储地址都是被写在了物理磁盘上,只有存在物理磁盘上,才能保证数据长久不丢失
我们来看看一个普通的磁面:
我们可以看到这个磁面上记录着磁道和扇区,
固定头每个磁道上都有一个读写头,造价高,但是读写速度快,定位时间短
我们在了解了我们的磁盘和移动头后,我们就需要了解一次物理磁盘的I/O,它指的是对于磁盘来说,一次磁盘的连续读或者连续写称为一次磁盘 I/O, 磁盘的 IOPS 就是每秒磁盘连续读次数和连续写次数之和。
一个扇区的大小比较公认的是512字节(后面慢慢发展的也有一个扇区2048字节的,我们这里就举例512字节)
我们先简单的看一个数据表,数据在扇区上是怎么存储的:
由此我们可以推出:这张表的一条记录就是8+40+16=64字节,我们这会儿定义的这张表的一条记录就要占64字节
所以一个扇区就只能装8条记录,我们这32条记录就需要32/8=4,就需要4个扇区去装入,
但我们简单的把记录加到800条的时候:800/8 = 100,也就是需要100个扇区来装入,那我们要查找第800条记录的时候就需要100次I/O操作,显然这样的I/O操作就太慢了,要是有1000个人需要查找,时间开销就很大了
二.MySql的索引
什么是索引呢?
简单的说,索引就是建表或者后期加入的,它可以分为主键索引,复合索引,普通索引,
这里我们再来简单的看两个表:
当id被选为索引以后,id会和id所在的实际物理地址构成一个表,这个表id 8字节,地址 8字节,一共16字节,它也是存在一个扇区的还有可能没有和数据原表在相邻的扇区
第一条记录:记录id为1,它所在的物理地址,
第三十二条记录:记录id为1023,它所在的物理地址
有了这个索引表之后,我们再查800条记录数据的过程就简单化了
然后,我们查第800条记录的时候我们很幸运,因为索引表中有一个区间是800~833就可以通过地址直接去读800所在的扇区 这里就也只用了一次I/O操作
比如:
33~65区间上,当我们要查询64时只能通过找到id=33的扇区,然后依次读取直到读到id=64的扇区
800~833区间上,我们去查找832时:
从800读到832一共是32条记录:32/8=4(扇区),也就是我们要连续读取4个扇区才可以找到id = 832这条记录,这就需要4次I/O
比起没有索引的查询:从第32条记录开始,就会成比例的不断增大读写次数
继续加大数据,这次存放80000条记录:
当数据量达到80000条的时候:我们的一级索引表(紧贴实际数据表的索引表被称为一级索引)就显得的很乏力了,
80000/1024 = 78~79,我们需要79个扇区来存储
对于80000条数据查询就需要83次I/O,很显然,这个I/O次数太多了,我们得想办法把I/O次数压下去
比如:
二级索引一条记录的就是一级索引区间的1~1025
1024 * 32 = 32768
这个时候利用二级索引查找80000:
1。
然后去一级索引上找,由于是二级索引提供的物理地址,只需要一次I/O就可以读取到那个扇区,一级索引上有一个区间就是80000~81025,
这是最好的一种情况:3+1+1=5,最好的状态5次I/O就可以拿到数据了
最坏的情况也是出现在一级索引去找数据:就是80000~80033这个区间
3+1+4=8
综上:查找80000条数据(最坏的情况)
b.一级索引,由于第80000条记录在最后一个扇区上,80000/1024 = 79,一级索引需要79次I/O,利用一级索引去查找数据4次I/O,一级索引需要83次I/O操作
到了这里我们就可以很明显的感受到索引的魅力了,其实讲到这里我们也可以很明显看到我们的B+树是怎么组织数据和索引的了
我们把上面的图片顺时针翻转90度,就可以很明显的看到我们的B+树就是这个模型
可能对博客中的例子存在的疑问:
不是,要根据开发人员的默认设置,或者后期数据库管理员去调整,一般人是更改不了物理存储的,只能了解原理
不是,要根据建立索引属性的大小和实际物理地址大小而定,不一定每个扇区都能存刚好存32条索引记录
不是,要根据一次读取的页面大小,MySql的默认读取是16KB:16kb / 64 =250 条记录,一般的查询一次I/O至少就是250条记录,
也就是64kb / 64 = 100条记录,在缓存中有一次I/O是有100条记录被返回,然后怎么查询就是InnoDB引擎所要了解的知识了
三.MySql中B+树索引存储结构的形成
这就是一颗较为完整的B+树了,我们在仔细的看看可以发现B+树的特征
b.根节点存放的都是索引,只有最下面一层的子节点才是数据
现在图片上描述的B+树,其实B树有很大一部分都能做到,我们就来看看B树和B+树的区别吧
B树和B+树的区别(主要的区别)
区别1:
可以说父节点可能既有索引又有数据,这就是B树的存储方式
总结:
B树,存在一种情况就是所查的数据在最上层,因为节点有数据可能第80000条记录在最上层区间上,所以一次I/O就可以拿到数据,最坏的情况就和B+树一样,要到最后一层才能拿到数据
感觉有时候B树比B+树快啊,为什么MySql要用B+树呢?
举个简单的例子,就以上面两张图片:我们要查询第7条数据和第8条数据,这两条记录是紧挨着的
第七条记录:1次I/O
使用B+树查询:
第八条记录:2次I/O
这就很明显阿可以看出B树的查询效率很不稳定,尤其是层数变多,数据区间变得的时候,就更加明显
区别2:
在B树上子节点和子节点是相互隔离开的,现在我们构造一种情况,B树中我们一条查询语句需要查询两条记录,
由于这是一条查询语句,所以要一起执行会发生什么,我们的磁头会先移动到根节点进行定位,然后就可以id = 6这条记录,然后从新去根节点查索引,磁头再定位到 id = 8 这条记录
所以,B+树在最后一层的数据结点上都加了指针(指向的是物理地址),让它指向下一个区间的开始位置,把尾部的数据又串起来了,就是专门对付这种相邻区间要重复磁头定位的情况
四.总结
上面所有的描述都只是B+树常规的数据存储方式,实际上MySql的运行存储比B+树要复杂的多,因为我们各自的设备或者后期对物理存储的默认参数不一样
需要真正的就业或者更进一步学习,MySql的认识还有很长的一段路要走