B树索引算法介绍

1.B树

B树又称为多路平衡查找树,它类似普通的平衡二叉树,不同的一点是B树允许每个节点有更多的子节点。

B树有如下特点:

  1. 具有n个关键字的节点含有(n+1)棵子树
  2. 所有键值分布在整棵树中(索引和data都在每个节点中)
  3. 任何一个关键字出现且仅出现在一个节点中
  4. 在进行查找时,最好情况为O(1),在关键字全集内做一次查找,性能逼近二分查找
  5. 所有叶子节点都出现在同一层次上,并且不带任务信息

2.B+树

B+树是B树的变体,也是一种多路查找树,与B树不同之处在于:

  1. 在B+树中,具有n个关键字的节点只有n棵子树,即每个关键字对应一个子树
  2. 在B+树中,叶节点包含信息,所有非叶节点仅起到索引作用,非叶节点中的每个索引项只含有对应子树的最大关键字和指向该子树的指针,不含有该关键字对应记录的存储地址
  3. 在B+树中,叶节点包含了全部关键字及指向相应记录的指针,而且叶节点中将关键字按大小顺序排列,并且相邻叶节点按大小顺序相互连接起来
  4. B+树通常有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,因此B+可以进行两种查找算法:一种是从最小关键字的顺序查找,另一种是从根节点的多路查找

为什么大多数关系型数据库索引选择B+树结构

通过上面对这三种索引的基本结构的简单介绍,接下来分析一下为什么关系数据库更愿意选择B+树作为默认索引。

首先分析B+树索引在关系型数据的优势

1)在关系型数据库中,由于数据量较大原因,导致构建的索引也非常大,所以需要把索引存储到外部磁盘,而B+树构建的索引更适合在外部磁盘存储,这是因为B+树的每个节点不存储数据,只存储索引,这样B+树的每个节点就会存储更多的索引(Innodb每个索引页(节点)在磁盘空间的默认大小为16KB),所以B+树的层数就会越低,因此索引查找时IO操作的次数就会减少

2)由于B+树的叶子节点的特性,使得B+树还有一个最大的好处,方便扫库,B树必须用中序遍历的方法按序扫库,而B+树直接从叶子结点挨个扫一遍就完了,因此使得B+树的遍历查找和排序操作都非常高效

分析为什么哈希索引不适合关系型数据库中

哈希索引只需要一次计算即可找到相应的健值,因此对于等值查询,哈希索引有绝对的优势,但是前提构造哈希索引的哈希函数很少产生关键字冲突,不然在哈希索引的过程中,需要根据处理冲突的方法查找哈希值,性能就不敢保证了。

1)哈希索引仅能满足“=”、“IN”和”<=>”查询,不能使用范围查询,因为哈希索引比较的是经过哈希预算过的哈希值,因此只能进行等值的过滤不能,不能基于范围的查找,因为经过哈希函数处理后的哈希值的大小关系,并不能保证与处理前的关键字大小关系对应。

2)哈希索引无法被用来进行数据的排序,由于哈希索引中存放的都是经过哈希计算之后的值,而哈希值的大小关系不一定与哈希计算前的值一样,所以数据库无法用哈希索引中的值进行排序

3)对于组合索引,哈希索引在计算哈希值的时候是组合关键字一起计算哈希值,而不是单独计算哈希值,所以通过组合索引的最左前缀匹配原则进行索引查询时,哈希索引无法使用

分析为什么B树索引不适合关系型数据库

1)没有像B+树拥有按顺序存储且含有data地址的叶子节点,导致B+树在排序和分区查询的时候性能比较低下

2)由于B树的每个节点包含了索引和数据,导致同样大小的节点存储的索引就会减少,这样树的高度就会增高,自然IO的次数就会增加

特别说明:这里仅仅分析了关系型数据库为什么选择B+树索引,并不是说B树索引和哈希索引就没有它们自身的优点,脱离使用场景谈效率都是不应该的。比如B树索引更常用在MongoDB数据库中,这是因为MongoDB是一种文档型、采用类json的bson数据格式进行数据存储的nosql数据库,数据结构比较灵活,举个例子:假如我们要建立一个电子商务网站,类似淘宝这种将商品销售给用户,那么必须存储用户信息、商品目录、订单、收货地址、账单地址、付款方式等。

关系型数据是如何存储的:

MongoDB则可以这样进行存储(右图是对应的bson格式):

MongoDB数据库的存储结构决定MongoDB是一种聚合型数据库,所以这就决定了MongoDB结构的灵活性,它完全抛弃了关系型数据库那一套体系之后,在设计和实现上就非常自由,可以更自由对特定场景进行优化,而在 MongoDB 假设的场景中遍历数据并不是常见的需求, 认为查询单个数据记录远比遍历数据更加常见,由于 B 树的非叶结点也可以存储数据,所以查询一条数据所需要的平均随机 IO 次数会比 B+ 树少,使用 B 树的 MongoDB 在类似场景中的查询速度就会比 MySQL 快(B树单个查询最好为O(1),最坏为log(n),而B+树单个查询始终是long(n)),这里并不是说 MongoDB 并不能对数据进行遍历,我们在 MongoDB 中也可以使用范围来查询一批满足对应条件的记录,只是需要的时间会比 MySQL 长一些。相反 MySQL 中使用 B+ 树是因为 B+ 树只有叶节点会存储数据并且通过指针连接起来,因此使得遍历效率很高,而遍历数据在关系型数据库中是非常常见的需求,所以它选择B+树作为底层索引结构。认清MongoDB和关系型数据库的使用场景,可以帮助我们更好的设计数据库,来提高我们数据库的查询性能。

组合索引在B+树上的存储结构及查找方式

大家都知道组合索引有一个最左前缀匹配原则,这个原则的产生也是由于组合索引在B+树中的存储结构决定的,下图是我简单画的一个组合索引的存储结构:

首先,表T1有字段a,b,c,d,e,其中a是主键,除e为varchar其余为int类型,并创建了一个组合索引idx_t1_bcd(b,c,d),然后b、c、d三列作为组合索引,在B+树上的结构正如上图所示。组合索引的B+树是根据组合索引的第一个索引进行构建,同时叶子节点按照第一个索引从左向右递增的,当第一个索引相同时,根据第二个索引排序,以此类推,因此组合索引只能从多列索引的第一列开始查找,所以如果你的查找条件不包含b列如(c,d)、(c)、(d)是无法使用组合索引的,以及跨列也是无法完全用到索引如(b,d),只会用到b列索引,因为需要对b索引的结果进行全局查找d。

mysql不同执行引擎的索引区别

本文主要是介绍索引,为什么会说到执行引擎呢,这是因为mysql不同执行引擎的索引实现还是有一些差别的,这里主要说InnoDB和MyISAM两个引擎之间的特点和差别:

InnoDB

  1. 支持事务操作(并且实现了SQL标准的四种隔离级别)
  2. 支持行级锁(查询速度快)和表级索
  3. 不支持全文索引(5.7以后的InnoDB支持全文索引了)
  4. 是聚簇索引(因为索引文件和数据在同一个文件下)
  5. 是数据库默认的存储引擎

MyISAM

  1. 不支持事务
  2. 不支持行级锁和外键
  3. 是非聚簇索引
  4. 支持全文索引
  5. MyISAM缓存记录了表的行数

非聚簇索引(MyISAM):索引文件和数据文件分开存储, B+树的叶子节点的data指向数据的实际地址

聚簇索引(InnoDB)InnoDB存储引擎表时索引组织表,按照主键构建B+树,叶子节点存放了整张表的所有记录,即索引文件包含了所有数据

InnoDB中会根据每张表的主键构建一个聚集索引,聚集索引的叶子结点包含了每条记录的全部信息,对与非主键索引会构建成辅助索引,叶子结点包含了主键,当通过辅助索引查找数据时,InnoDB存储引擎会遍历辅助索引并通过叶子结点获取主键,然后通过主键查找主键索引查找完整记录。

基于以上对聚簇索引和非聚簇索引的理解,导致这两个执行引擎适用的场景是不同,MyISAM适用于读密集的表,主要有两个原因:一个原因是InnoDB为了保障事务的隔离性,导致读取效率没有MyISAM高。

InnoDB索引优化

Innodb索引优化-索引覆盖

如果辅助索引包含了查询内容,若不符合最左前缀原则,则 type为 index,若符合,则 type 为 ref

Innodb索引优化-索引选择

tb_order共1000条数据,有order_id聚集索引和order_code辅助索引,下面sql会选择哪个索引?

explain select * from tb_order where order_code > 1 and order_code < 500

会选择order_code索引,原因在于用户要选择的数据是整行信息,而order_code索引不能覆盖到我们要查询的信息,因此对于order_code索引查询到指定数据后,还需要一次回表查询整行数据。虽然order_code在叶节点是顺序存放的,但是order_id是无序的,因此回表查询就会变成离散读。如果访问的数据量很小,则优化器还是选择辅助索引,但是访问数据超过整个表的20%,优化器会选择直接通过聚簇索引查询数据,因为顺序读要远远快于离散读

Innodb索引优化-MRR(Multi-Range Read)

MRR是MySQL5.6版本开始支持的功能,MRR可以帮我我们在回表查询时,在查询辅助索引时,首先根据得到的查询结果,按照主键进行排序,然后按照主键排序的顺序进行回表查询,这样可以减少随机读带来的性能消耗,同时可以降低缓存中的数据页刷新的频率

t有(key_part1, key_part2)的联合索引select * from t where key_part1 >=1000 and key_part1 < 2000 and key_part2 = 10000;优化器会将查询条件拆分成(1000,10000),(1001, 10000),(1002,10000),…,(1009, 10000)

Innodb索引优化-ICP(Index Condition PushDown)

和MRR一样,ICP也是MySQL5.6版本开始支持的功能,可以帮助我们将WHERE过滤放到存储引擎层。比如下面的SQL语句,在不支持ICP的MySQL版本会先根据索引查找记录,然后再根据WHERE过滤条件。在支持ICP后,数据库在取出索引的同时,会根据索引进行WHERE过滤,这样可以大大减少上层SQL对记录的索取(fetch),从而提高数据库的整体性能。我们可以通过执行计划中的Extra属性是否使用using condition index了解数据库是否使用了ICP

t有(key_part1, key_part2, key_part3)的联合索引select * from t where key_part1 =1000 and key_part3 = 3000;

B+树在MySQL索引的应用和InnoDB的索引优化相关推荐

  1. MySQL聚集索引详解_MySQL innodb 聚集索引的概念与使用教程

    聚集索引是指数据库表行中数据的物理顺序与键值的逻辑(索引)顺序相同.一个表只能有一个聚集索引,因为一个表的物理顺序只有一种情况,所以,对应的聚集索引只能有一个. 在MySQL中,InnoDB引擎表是( ...

  2. 创建二级索引_技术分享 | InnoDB 排序索引的构建

    原创: 管长龙 译 爱可生开源社区 3天前 作者:Satya Bodapati 从 MySQL 5.7 开始,开发人员改变了 InnoDB 构建二级索引的方式,采用自下而上的方法,而不是早期版本中自上 ...

  3. mysql innodb 索引组织表_Mysql InnoDB引擎 -索引组织表

    在InnoDB 存储引擎中,表都是根据主键顺序组织存放的,这种存储方式的额表称为索引组织表.在InnoDB存储引擎表中,每张表都有个主键(Primary key),如果在创建表时 没有显示地定义主键, ...

  4. 大于小于优化_以MySQL为例,详解数据库索引原理及深度优化

    本文内容主要来源于互联网上主流文章,只是按照个人理解稍作整合,后面附有参考链接. 一.摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引 ...

  5. 大于小于优化_架构 - 以MySQL为例,详解数据库索引原理及深度优化

    一.摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如 ...

  6. mysql listagg函数 长度过长_MySQL索引是什么?怎么做?

    首先,MySql 支持多种存储引擎,最为常用的是 innodb,MyIsam 也需要了解,其他的存储引擎包括 Archive 等等都要有个印象. 各种存储引擎对于索引的支持也不相同,总结下来,MySq ...

  7. 由B+树看MySQL索引结构

    当我们发现SQL执行很慢的时候,自然而然想到的就是加索引.对于范围查询,索引的底层结构就是B+树.今天我们一起来学习一下B+树,从B+树来看MySQL索引结构. 文章目录 B树 B+树 为什么使用B+ ...

  8. mysql索引 b树_B树与MySQL数据库索引.ppt

    B树与MySQL数据库索引 * B+树及MySQL数据库索引 厦门大学数据库实验室 罗道文 2014-08-02 ?B树以及B+树的特点以及原理 ?MySQL存储引擎MyISAM和InnoDB的B+树 ...

  9. 阿龙的学习笔记--- B-树和B+树 以及 MySQL的索引机制总结

    B-树和B+树原理详解:https://blog.csdn.net/ywlmsm1224811/article/details/97890446 深入理解MySQL索引之B+Tree: 写得好!Inn ...

最新文章

  1. 2018-2019 ACM-ICPC, Asia Nanjing Regional Contest
  2. 一种投影法的点云目标检测网络
  3. 找出数组中最长的连续数字序列(JavaScript实现)
  4. python字典内存分析_Python减少字典对象占用的七成内存
  5. 反思应对焦虑:尽人事 听天命
  6. 用python写helloworld_Python Helloworld程序简单实现
  7. 硬件创新需要去理解的点(精炼总结)
  8. python getostime_python转换在os.utime中使用的datetime
  9. C++11标准之NULL与nullptr比较
  10. 一行命令搞定node.js 版本升级
  11. Excel远程连接Oracle,excel连接数据库_怎么用oracle命令连接远程数据库�9�3
  12. 一个人最顶级的修养,不与烂人烂事纠缠
  13. awesome-spider
  14. 美团2023届笔试题解
  15. 几种字符集与LPTSTR、LPCSTR、LPSTR、LPCTSTR、LPWSTR、LPCWSTR的意义
  16. 玩转Django2.0---Django笔记建站基础九(一)
  17. 响应式布局有什么优点和缺点
  18. mybatis的<choose>和<otherwise>使用
  19. Pycharm图形化性能测试工具Profile
  20. TX9116同步升压ic

热门文章

  1. 10g recyclebin与用户表空间限额
  2. python变量说法_Python不允许使用关键字作为变量名,允许使用内置函数名作为变量名,但这会改变函数名的含义...
  3. 怎么查看笔记本内存条型号_笔记本内存条型号简介以及查看方法【图文教程】...
  4. 宝贝不哭,妈妈打它--转贴
  5. autojs之大柒侧滑栏详解
  6. 富有组织性是通往成功的必要习惯
  7. 免费的Office办公套件LibreOffice for Mac
  8. 各种区块链浏览器的地址总汇
  9. 昭和女神异闻录——中山美穗
  10. Apollo 参考线平滑方法Fem Pos Deviation Smoother