索引面试不用总是问“为什么要使用B+树作为索引”

1 构建索引需要考虑的因素

1.1 计算机存储结构

计算机存储结构如下图所示,从上到下依次为寄存器、高速缓存、主存储器、辅助存储器。其中主存储器,即我们常说的内存;辅助存储器也被称为外存,比较常见的就是磁盘、SSD等。在这个存储结构中,每一级存储的速度都比上一级慢很多,所以程序访问越上层存储中的数据,速度就会越快。

1.2 局部性原理与磁盘预读

  • 起因:内存读写快,磁盘读写慢,而且慢很多;
  • 磁盘预读:磁盘读写并不是按需读取,而是按页预读,一次会读一页(一般为4KB, MySQL为16KB)的数据,即每次加载更多的数据。如果未来要读取的数据就在这一页中,可以避免未来的磁盘I/O,提高效率;
  • 局部性原理:软件设计要尽量遵循“程序运行期间所需要的数据比较集中”和“当一个数据被用到时,其附近的数据也通常会马上被使用”,这样磁盘预读能充分提高磁盘I/O。

1.3 索引设计考虑因素

数据库索引因数据量较大,一般都是存储于外存中,而程序是在内存中执行的,这样就需要进行频繁的I/O操作,那么,为了减少I/O次数,该怎么做呢?我们知道,磁盘预读是按页操作的,如果每一页包含的信息量足够大,是不是就可以达成目的了。

索引设计需要考虑的第一个核心因素:保证每页包含尽可能多的关键信息,来减少磁盘I/O

2 可提升查找性能的数据结构

添加索引的目的,主要是为了提升数据库的查找速度。一般来说,可提升查找速度的数据结构有以下两种:
(1)哈希。比如HashMap,其查询、插入、删除的平均时间复杂度均是O(1);
(2)树。比如二叉查找树,其查询、插入、删除的平均时间复杂度均是O(log(n))。

可以看到,论时间复杂度,不管是读请求,还是写请求,哈希的性能会更好,可为什么DB却选择使用B+树呢?接下来,我将按“哈希表 -> 平衡二叉树 -> B树 -> B+树”的思路逐个进行分析。

索引设计需要考虑的第二个核心因素:结合DB各种搜索场景,选取更合适的数据存储结构

3 哈希表

假设采用HashMap存储,如果查询sql都是单行查询,比如

select * from user where name='zhangsan';

那么,采用哈希确实很快,但是,如果过滤条件是范围(<、>),排序(order by)等查询场景呢?其时间复杂度将退化为O(n)。假设我们采用的是“m叉查找树”,由于其本身是排好序的,其时间复杂度仍将是O(log(n)),即仍能保证其高效率。

所以,相比“m叉查找树”而言,后者更加合适。

哈希表:指定数据的定位较快,范围查询较慢

4 平衡二叉树(AVL树)

平衡二叉树的结构如下图所示,可以认为它是升级版的二叉树,它有两个特征:

  • 数据是有序排列的
  • 任何节点的儿子子树高度差的绝对值不会超过1
  • 采用中序遍历可获得所有节点


从图中可以看出,每个节点有且仅能存储一个记录,如果数据量大的话,树的高度将会很高,故而,当查询数据时,会产生很多次磁盘I/O。

相比哈希表而言,平衡二叉树支持范围查询,解决了哈希表的痛点

5 B树(平衡多路查找树)

B树的结构如下图所示,它有以下特点:

  • 叶子节点和非叶子节点都存储数据(此特点会导致非叶子节点不能存储大量的索引)
  • 采用中序遍历亦可获得所有节点


从图中可以看出,每一个节点可以有多个子节点,且每一个节点(包括非叶子节点)均存储数据,采用中序遍历便可查找到所有数据。但是,数据库磁盘交互是按页为单位(MySQL默认为16K)的,如果数据量过多时,每个节点存储的键值会较少,进而树的高度比较高,导致磁盘I/O比较多。同时,在实际项目中,范围查询的SQL比较频繁,倘若采用B树作为索引结构,需要中序遍历很多节点,来收集符合筛选条件的数据集。因此,此结构某种程度来看,不是太合适。

6 B+树

B+树的结构如下图所示,它有以下特点:

  • B树的升级版
  • 非叶子节点仅保存索引和指针(不再存储数据),仅叶子节点存储数据信息(保证节点可以存储更多索引,进而减少树的高度)
  • 叶子节点间采用了链表,这样,范围查询时,只要确定范围的左右边界坐标,遍历叶子节点链表,便可获取所有符合条件节点集合


从其特点可得知,它兼具了“降低树高度,减少磁盘I/O”、“提升范围查询性能”两个因素。

接下来,举一个例子来说明B+树怎么控制树的高度的。
我们假设一页大小是16KB,每个索引(主键)是bigint类型,即8B,指针为6B。那么每页能存储大约1000个索引(16KB/(8B+6B) \approx1000)。
那么,一颗3层的B+树能够存储多少索引呢?如下图:

大约能够存储10亿个索引。通常 B+ 树的高度在2-4层,由于 MySql 在运行时,根节点是常驻内存的,因此每次查找只需要大约2-3次IO。

7 番外篇 —— 索引构建注意事项

结合索引的底层原理,我们在实际项目中构建索引时,需要注意以下几点:

  • 主键不能太大,否则,每个节点可容纳的节点会较少
  • 主键最好是自增的,否则,每次插入都会调整B+树,从而导致页分裂,影响性能

参考资料:
[1] BTree和B+Tree详解 https://www.cnblogs.com/vianzhang/p/7922426.html
[2] Mysql的常见面试题 + 索引原理分析 https://www.cnblogs.com/hulianwangjiagoushi/p/10537909.html
[3] 数据库索引融会贯通 https://juejin.im/post/5c67becf6fb9a049a42f9420
[4] 数据库索引为什么用B+树实现 https://juejin.im/post/5c67bf756fb9a049e4133cd9
[5] 20分钟数据库索引设计实战 https://juejin.im/post/5c67bf296fb9a049a81fdbde
[6] 数据库索引,到底是什么做的 https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651961486&idx=1&sn=b319a87f87797d5d662ab4715666657f&chksm=bd2d0d528a5a84446fb88da7590e6d4e5ad06cfebb5cb57a83cf75056007ba29515c85b9a24c&mpshare=1&scene=1&srcid=0228KnNLEEqCDuKngwvMur4c&key=d1883245a7b0616ccde09505e7184e8a33fad3848d4f804f91885bdad93a1b2aea22333148db09073f09f8c977e09f871a3cdc9c546be12bbe6b44a1d66fc209efeb4cb3a1f5eff2dd240556723964b3&ascene=0&uin=MjMwMzU4MDU2MQ%3D%3D&devicetype=iMac+MacBookPro12%2C1+OSX+OSX+10.14+build(18A391)&version=12020810&nettype=WIFI&lang=zh_CN&fontScale=100&pass_ticket=WOB52g58BXxtmtWDGbQLQhPhwwKkAErjlrx2uOM5oMnULMc9fOC9ptI%2BaWQpLWVs
[7] MySql 三大知识点——索引、锁、事务 https://maimai.cn/article/detail?fid=1188457423&efid=b6VprMXHZGlLNLckx8yfAQ

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容

  • B树的定义 一棵m阶的B树满足下列条件: 树中每个结点至多有m个孩子。 除根结点和叶子结点外,其它每个结点至少有m...
    文档随手记阅读 13,161评论 0 25
  • 作者: 张洋原文地址:http://blog.codinglabs.org/articles/theory-of-...
    IT程序狮阅读 1,261评论 1 19
  • 此时此刻,已经是夜里十一点时分,韩晨辗转在床,手机就放在枕边,他在等何美丽的短讯。 按道理早就该来短讯了。 出什么...
    大林家阅读 267评论 0 1
  • 我难过不是因为你欺骗我,而是因为我再也不能相信你。
    TIEDPAG阅读 199评论 0 0
  • 2019年是结婚的第六个年头了,加上认识恋爱的一年也快到七年之痒了。昨天是元旦,我发了一个朋友圈,内容是我...
    真真_3d37阅读 842评论 7 15