文章目录
一、什么是索引
索引是帮助MySQL搞笑获取数据的排好序的数据结构
在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。
索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序。数据库使用索引以找到特定值,然后顺指针找到包含该值的行。这样可以使对应于表的SQL语句执行得更快,可快速访问数据库表中的特定信息。
–来自百度百科
二、索引数据结构
1.二叉树
可以提前了解一下:二叉搜索树
左边是没有索引的情况,右边是作为col2字段 二叉树索引的情况。
假如执行查找(假设表为 test)
select *from test where col2 = 89;
那么,左边的情况,需要比较6次才能找到,右边的情况,只需要比较2次就可以找到。当数据量非常大时,要查找的数据又非常靠后,那么二叉树结构的查询优势将非常明显。
二叉树索引存在的问题
我们都知道二叉搜索树是存在极端情况的假如我们的第一个索引数据为最小的那么就单边增长会形成链式这样查询复杂度和不用索引一样的都是O(n)
2.红黑树
我们可以提前了解一下:红黑树
红黑树可以有效的解决二叉树的极端问题保持平衡
红黑树当索引的问题
红黑树最大问题是高度问题。
假设现在数据量有100万,那么红黑树的高度大概为 100,0000 = 2^n, n大概为 20。
那么,至少要20次的磁盘IO,这样,性能将很受影响。如果数据量更大,IO次数更多,性能损耗更大。
3、Hash表
Hash是MySQL中支持的两种索引结构中的一种。
Hash的大致原理是:
事先将索引通过 hash算法后得到的hash值(即磁盘文件指针)存到hash表中。
在进行查询时,将索引通过hash算法,得到hash值,与hash表中的hash值比对。通过磁盘文件指针,只要一次磁盘IO就能找到要的值。
Hash表存在的问题
我们知道Hash表查询是通过计算出Hash值进行直接定位数据磁盘位置,计算速度式非常快的,而且数据库底层中去尽量避免了Hash碰撞的问题,既然不是Hash碰撞问题那么是什么问题呢?
条件查询 我们试想我们假如要查询多条数据比如查询比某个字段值大的数据这时候Hash表就无能为力了。
MySQL支持Hash当索引
当我们表中几乎全是用的单条查询的时候我们可以选择Hash索引,因为Hash索引查询单条语句的速度是十分快的
4、B-Tree
B-Tree 是一种平衡的多路查找(又称排序)树,在文件系统中和数据库系统有所应用,主要用作文件的索引。其中的B就表示平衡(Balance)。
BTree是满足下列条件的数据结构:
- 叶子节点具有相同的深度,叶节点的指针为空
- 所有索引元素不重复
- 节点中的而数据索引从左到右递增排列
BTree索引能很好解决高度问题。也就是我们红黑树当索引的问题
B-Tree存在问题
问题一:
假如我们查询如下条件的数据
select *from test where col1 > 20;
那么不但需要叶子节点>20的值,也需要非叶子节点在右边节点的值。即下图圈的两部分:
我们可以看到在范围查找上B+树好像有点问题
问题二:
为了降低树的高度我们扩宽了树的深度,我们层层IO的时候读取大小如果太大的话IO效率也会降低,B-Tree采用节点+指针 很占用空间的
5、B+Tree
B+Tree(B-Tree变种)
- 非叶子节点不存储data,只存储索引(冗余),可以放更多的索引
- 叶子节点包含所有的索引字段
- 叶子节点用指针连接,提高区间访问性能
结构
一个节点是由索引+指针组成的
节点左边的指针指向的是小于节点值的索引,右边指针值的是大于节点值的索引
优点
解决了B-Tree的问题,我们可以看到B+树上两层都是存放的索引,最后一层存放的索引+数据,最后一层的索引和上两层的是冗余的,这样的话两层可以去放更多的索引
那么B+tree可以支持多少数据的查找呢?
MySQL 官方对非叶子节点(如最上层 h = 1的节点,B+Tree高度为3) 的大小是有限制的,最大的大小是16K,可以通过以下SQL语句查询到当然这个值是可以调的,既然官方给出这个阈值说明再大的话会影响磁盘IO效率
SHOW GLOBAL STATUS like 'InnoDB_page_size';
一个节点的大小:索引+指针 索引节点类型Bigint(8B)+指针大小(6B)=14B
第一层和第二层存放的全是节点那么第一层第二层可以存放的节点数:16k/14B=1170
第一层可以存放1170个节点 每一个节点都有指针,指针指向下一块每一块大小都是16K也就是1170个节点依次类推第三层可以有11701170快16k的空间。假设我们第三城每个数据是1K的话那么一块可以存放16个data数据总共就是11701170*16条数据.
1170117016=21,902,400 也就是说我们B+tree可以存放2000w条数据
范围查找
当我们到了第三层执行范围查找的话,MySQL底层采用的B+Tree是双向链表我们找到之后可以顺藤摸瓜的往下查找就可以