mysql索引原理,看这篇就够啦

前言

网上已经有了很多相关mysql索引原理的文章,但是都存在一些问题,有的是直接复制别人的比较老的文章,有的直接开篇讲B+Tree的原理,过程不是很清楚,即使原理讲清楚了,没有各种数据结构的对比也很难体现出B+Tree的优越性,其实我觉得从一些问题来看,然后根据发现问题解决问题的思路来看,这样可能学习效果会更好,所以写了这篇文章,希望你能喜欢

问题列表

1:数据库中最常见的优化方式是什么?
加索引(相信这个大家都知道)
2:为什么加索引能优化慢查询?
。。。。。
3:哪些数据结构可以优化查询速度?
。。。。。
4:这些数据结构都可以优化查询速度,为何mysql会选择B+Tree
。。。。。
\color{#FF0000}{5:数据库能存多少数据?大概数据达到多少会到达峰值?计算依据是什么?}
\color{#FF0000}{。。。。。}

数据库查询过程

对于一般字段而言,mysql查询都是采用的全表扫描的方式来进行数据查询

WechatIMG111007.png

比如查找
select id from Test where age =1;
扫描第一次就能找到,如果查找
select id from Test where age =7;
可能扫描到第八次才能找到,如果数据非常多,多达几千万行,查找数据最极端的情况下可能需要查找到最后一次才能找到业务所需数据,所以是非常耗时的,我们就需要对数据查找过程进行优化,其实mysql索引就是一种数据结构,来优化查询速度的。方便我们查找数据(包括范围查找和指定查找)

索引的几种数据结构

在这里先给大家介绍一个网站
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
这个网站可以模拟各种数据结构的插入和查找的动画过程,这样更容易理解

二叉树

二叉树其实就是遵循了一个规律来排列,左小右大


二叉树.png

这样的话比比如我们查询9 通过两次比对就可以查询到

但是二叉树这种数据结构存在一些问题,比如数据是递增或者递减的顺序插入,二叉树就很容易形成单路链表


单路链表

如果遇到这种情况那么查找数据就普通的没有加索引的情况没什么区别了

红黑树

红黑树是一种自平衡二叉查找树,平衡二叉树的目的是为了减少二叉查找树层次,提高查找速度
比如依次插入 1到9,二叉树可能就和上图所展示的单路链表一样,红黑树可以自动旋转,减少层数

红黑树.png

具体过程可以在下面链接中插入看演示
https://www.cs.usfca.edu/~galles/visualization/AVLtree.html

散列表(hash)

散列表也为哈希表,又直接寻址改进而来。在哈希的方式下,一个元素k处于h(k)中,即利用哈希函数h,根据关键字k计算出槽的位置。函数h将关键字域映射到哈希表T[0...m-1]的槽位上


散列表

散列表的缺点
1)Hash 索引仅仅能满足”=”,”IN”和”<=>”查询,不能使用范围查询。
2)Hash 索引无法被用来避免数据的排序操作。
3)Hash 索引不能利用部分索引键查询。
4)Hash 索引在任何时候都不能避免表扫描。
5)Hash 索引遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高。

B树

为了描述B-Tree,首先定义一条数据记录为一个二元组[key, data],key为记录的键值,对于不同数据记录,key是互不相同的;data为数据记录除key外的数据。那么B-Tree是满足下列条件的数据结构:

  • d为大于1的一个正整数,称为B-Tree的度。
  • h为一个正整数,称为B-Tree的高度。
  • 每个非叶子节点由n-1个key和n个指针组成,其中d<=n<=2d。
  • 每个叶子节点最少包含一个key和两个指针,最多包含2d-1个key和2d个指针,叶节点的指针均为null 。
  • 所有叶节点具有相同的深度,等于树高h。
  • key和指针互相间隔,节点两端是指针。
  • 一个节点中的key从左到右非递减排列。
  • 所有节点组成树结构。
  • 每个指针要么为null,要么指向另外一个节点。
  • 如果某个指针在节点node最左边且不为null,则其指向节点的所有key小于v(key1)v(key1),其中v(key1)v(key1)为node的第一个key的值。
  • 如果某个指针在节点node最右边且不为null,则其指向节点的所有key大于v(keym)v(keym),其中v(keym)v(keym)为node的最后一个key的值。
    如果某个指针在节点node的左右相邻key分别是keyikeyi和keyi+1keyi+1且不为null,则其指向节点的所有key小于v(keyi+1)v(keyi+1)且大于v(keyi)v(keyi)。


    BTree

另外,由于插入删除新的数据记录会破坏B-Tree的性质,因此在插入删除时,需要对树进行一个分裂、合并、转移等操作以保持B-Tree性质,而且B-Tree也是不支持范围查找的,所以一般不采用

B+树

B+Tree其实和BTree类似,但是也有很多区别,我们先看图

image

B+Tree的特征
1:每一个父节点的元素都出现在了子节点中,是节点的最大或者最小元素
比如上面事例图中的元素8和15
image

需要注意的是,根结点的最大元素(这里是15),也是整个B+Tree的最大元素
2:由于父节点的元素都出现在了叶子节点,因此所有的叶子节点包含了全部元素信息,并且每一个叶子节点都带有指向下一个叶子节点的指针,形成了一个有序链表
B+Tree的叶子节点

3:在BTree中,每一个节点都包含了数据,但是在B+Tree中,只有叶子节点包含了数据,中间节点仅仅是索引,没有任何数据关联
image

注意:聚簇索引(Innodb)的叶子节点包含了整行数据和索引

\color{red}{注意:对于聚簇索引来说,}
\color{red}{仅仅是主键的索引最终节点包含了数据本身,}
\color{red}{而非主键的叶子节点保存的是主键的值,}
\color{red}{然后再根据主键索引的值走B+树来查找数据本身,}
\color{red}{这么做的目的是为了一致性和节省存储空间}

innodb的索引如图所示


innodb索引.png

而非聚簇索引(myisam)的叶子节点只包含了索引,而不包含数据行本身
其实从数据库保存文件也能看出来,对于非聚簇索引(myisam)的表来说,数据库保存了三个文件
user_m.frm 表结构定义数据
user_m.MYD 表数据
user_m.MYI 索引文件
myisam索引如图所示


mysiam索引.png

而非聚簇索引(Innodb),数据库只保存了一个文件user_i.frm 所以说他的索引和数据是在一起的。
有一个非常形象的例子大家可以理解一下
非聚簇索引(myisam)相当于是一本书前面的目录,咱们可以根据目录去找到对应的内容
而聚簇索引(Innodb)相当于是书每一页下面的页码,页码和书本的内容是在一起的
B+Tree的优势

  1. 在单元素查询的时候,B+Tree会从根节点,逐层向下查找,最终找到要匹配的叶子节点,只需要三次磁盘IO就能找到,这个流程看起来和BTree差不多,其实并不是这样
  • 首先B+树的非叶子节点不包含数据,所以同样的磁盘页可以容纳更多的节点元素,所以相同的数据情况下,B+Tree会显得更加“矮胖”,所以查询磁盘IO的次数会少
  • 另外B+Tree的查询必须最后查找到叶子节点,而B-Tree只要找到了元素即可,不一定必须是得找到叶子节点,所以B-Tree的查询性能很不稳定,B+Tree的查询性能相对稳定很多。
  1. 对于范围查询来说B-Tree非常麻烦,如下图


    image

    比如我想查找大于3的数据
    中序遍历到元素6:
    中序遍历到元素8:
    中序遍历到元素9:
    中序遍历到元素11,遍历结束:


    image

    这种回环运算非常麻烦
    像B+Tree就简单了很多

    直接叶子节点链表指过去就行


    image

最后总结一下B+Tree的特征和优势
B+树的特征:

  • 有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。

  • 所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。

  • 所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。

B+树的优势:

  • 单一节点存储更多的元素,使得查询的IO次数更少。

  • 所有查询都要查找到叶子节点,查询性能稳定。

  • 所有叶子节点形成有序链表,便于范围查询。

索引下推

符合索引(age,name)
在5.6之前
先根据name把所有数据查询出来,然后在server层进行age所有字段筛选
在5.6 之后
从存储引擎拉取数据的时候,会根据age 和name两个字段做筛选,将符合条件的数据拉回

计算数据库能存储多少数据的方法(大概计算)

首先每个索引页可以存储的大小是16kb,这个值可以查到

show global status like 'innodb_page_size'

计算方法如图


innodb索引.png

辅助索引

上面我们说的其实都是基于主键索引,如果非主键索引(辅助索引)查询数据是什么样的呢?
① 在辅助索引上检索name(这个name是例子,意思是代表非主键索引),到达其叶子节点获取对应的主键;
② 使用主键在主索引上再进行对应的检索操作
这个过程也被称为回表


覆盖索引.png

之所以这么做的原因是 保证数据一致性和节省存储空间,可以这么理解:商城系统订单表会存储一个用户ID作为关联外键,而不推荐存储完整的用户信息,因为当我们用户表中的信息(真实名称、手机号、地址)修改后,不需要再次维护订单表的用户数据,同时也节省了存储空间

select * from table where name = ‘123’;
select id from table where name = ‘123’;
两个表查询的过程是不一样的 select * 需要回表
覆盖索引:在查询普通索引的时候,如果叶子节点保存的刚好是要查询的字段,此时叫覆盖索引

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容