千万级数据mysql索引原理深入剖析

第一章:mysql索引的本质

1.索引的重要性

从mysql数据库中查找书籍,就类似于从图书馆找书,如果书比较少,那么查找的速度会比较快,如果书比较多的时候,那么查找的速度就会非常的慢。这个时候图书的分类管理就显得非常重要了,图书分类管理就类似于索引(或者理解成给所有的图书设定目录)。

书很少时
在这里插入图片描述

书很多时
在这里插入图片描述

2.mysql索引常见的面试题

问一:数据库中最常见的慢查询优化方式是什么?
答:加索引可以优化查询。

问二:为什么加索引能优化慢查询?
答:因为索引是一种优化查询的数据结构,比如mysql中的索引是用B+树实现的。而B+树就是一种数据结构,可以利用索引快速查找数据。所以能优化查询。

问三:哪些数据结构可以提高查询速度?
答:哈希表 完全平衡二叉树 B树 B+树等。

问四:那这些数据结构既然都能优化查询速度,那mysql为什么选择使用B+树?
这个问题的答案就需要慢慢道来啦!!

3.mysql索引的本质

mysql中有这样一张表,user表,表结构的数据如下

在这里插入图片描述

假如在没有索引的情况下,当你执行如下的sql语句,那么执行的速度相对来说比较慢。
Sql语句如下:select * from user where id = 7

在没有索引的情况下,为什么查询的速度会比较慢呢??
因为数据都是存储在磁盘上的,那么再执行sql语句的时候,一定会去磁盘上读取相关的数据,那就会产生磁盘IO。如果没有索引,当你查询id=7的数据时,那么会进行7次磁盘的IO操作,比较耗费时间。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

当需要从磁盘读取数据的时候,操作系统会将数据逻辑地址传给磁盘,磁盘的控制电路按照寻址逻辑将逻辑地址翻译成物理地址,即确定要读的数据在哪个磁道,哪个扇区。为了读取这个扇区的数据,需要讲磁头放到这个扇区的上方。为了实现这一点,磁头需要移动对准相应的磁道。这个过程叫寻道,所消耗的时间叫做寻道时间。然后磁盘旋转将目标扇区旋转到磁头下,这个过程消耗的时间叫做旋转时间。

为什么要使用索引?

其目的就是为了减少磁盘的IO操作,这样就可以提高查询数据的速度。

索引本质是什么?

索引是帮助快速检索出数据的数据结构。
索引的作用是快速检索出数据。
索引的本质就是一种数据结构。也就是说你创建了一个索引,其实mysql的数据库会帮你创建一个数据结构,然后使用该数据结构来存储数据,该数据结构就是索引。

第二章:mysql索引底层原理

1.常见的数据结构

哈希表(散列表)、二叉树(完全平衡二叉树)、B树、B+树等等。

2.哈希表

哈希表是一种以键-值(key-value)的方式存储数据的结构,我们只要输入待查找的值(即key),就可以找到其对应的值(即Value)。哈希的思路很简单,把值放在数组里,用一个哈希函数把key换算成一个确定的位置,然后把value放在数组的这个位置,即idx = Hash(key)。如果出现哈希冲突,就采用拉链法解决。
因为哈希表中存放的数据不是有序的,因此不适合做区间查询,适用于只有等值查询的场景。

假如mysql的索引使用哈希表数据结构。默认主键列建立索引。
在这里插入图片描述

哈希表的缺点:因为节点的数据容易出现重合,查询数据还需要拿到真实的数据做对比,效率会变低。并且也不适合做范围查询。

3.二叉树

采用二叉树做为索引的数据结构。
二叉树是一颗相对平衡的有序二叉树,对其进行插入,查找,删除等操作性能都比较好。
特点:它的左子节点的值比父节点的值要小,右节点的值要比父节点的大。
自己测试例子
在这里插入图片描述

二叉树的优点:可以优化磁盘IO的次数。节点存在有顺序,可以进行范围的查询。
二叉树的缺点:插入数据的速度会比较慢,因为会更改数据结构。不平衡的问题,会产生倾斜的二叉树。

4.完成平衡二叉树

插入数据会平衡,但是插入的时候会改变树的结构。插入的数据的时候比较慢。而且树的层级会变高,会增加磁盘IO的次数。
二叉树是有顺序的,范围查找都是支持的。
在这里插入图片描述

5.B+树

B+树

B树或者B+树的节点可以存储多个数据,所以相对于完全平衡二叉树的高度肯定会低,那么就会降低磁盘IO的次数。
B+树相对于B树有数据的冗余,叶子节点中的数据是有顺序的。那么再进行顺序查找的时候就非常的方便,只要在叶子节点顺序向后遍历即可。

第三章:mysql索引底层原理分析

1.mysql中是如何使用B+树的

mysql中Innodb和myisam存储引擎默认都是使用B+树数据结构做索引的,存储的数据结构如下:
在这里插入图片描述

为什么只有叶子节点会存储数据,而非叶子节点不存储数据呢?

局部性原理:当一个数据被用到时,其附近的数据也可能被使用,所以操作系统为了提高效率,读取数据的时候往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,操作系统也会从这个位置开始,顺序向后读取一定长度的数据放入内存中,这里的长度叫做页。也就是计算机操作系统操作磁盘的基本单位,一般操作系统中一页的大小为 4kb。
在mysql中可以使用如下的命令查看Innodb引擎页的默认大小
SHOW GLOBAL STATUS LIKE ‘Innodb_page_size’
Mysql的页的大小默认是16kb,B+数的设计非常适合读取数据。
如果节点又存储数据和索引,数据比较多,索引就比较少,那么树的高度就越高。导致磁盘IO变多,效率变低。

2.B+数高度和存储数据的条数

一个节点能存储16KB的数据,这是mysql默认的节点大小,一页16KB。
假设一行记录的大小为1kb(其实已经比较大了)
那么一个叶子节点就能存储16条数据。
非叶子节点里面存储的是索引的值和指针,mysql默认的索引值大小是8B,指针大小是6B,合在一起是14B。那么非叶子节点可以存储的索引+指针的个数为:
16*1024/14 = 1170 个

那么如果数的高度是2层,叶子节点的个数也就是 1170个,那么可以存储的数据条数为:1170 * 16 = 18720条。

如果树的高度是3层,那每个叶子节点可以存储的条数为:1170117016= 21902400条

3.myisam引擎存储结构

可以使用命令创建一张新的表结构,使用myisam引擎来创建。Myisam引擎的索引采用的非聚集索引,索引和表数据是分开存储的。
在这里插入图片描述

user2.frm文件是创建表的文件
user2.MYD文件是表的数据文件
user2.MYI文件是索引文件

myisam引擎的索引结构图。
索引文件
在这里插入图片描述

数据文件
在这里插入图片描述

Myisam引擎通过索引查找数据的时候,通过索引值找到对应的地址,通过地址找到数据。

如果已name字段设置索引,效果是一样的。

4.Innodb引擎存储结构

数据文件
file

user.frm是创建表的文件
user.ibd是数据+索引文件
索引Innodb引擎是聚集索引,索引和数据文件在一起的。
在这里插入图片描述

如果已name字段设置索引,那就是二级索引。叶子节点中存储的该列的数据和主键值,也就意味着还需要再通过主键去查找一次数据。
在这里插入图片描述

学习更多架构免费课程请关注:java架构师免费课程
每晚20:00直播分享高级java架构技术
扫描加入QQ交流群264572737
在这里插入图片描述
进入群内免费领取海量java架构面试题
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章