MySQL的索引结构为什么是B+树?_navicat为什么只能创建的索引结构是b树-程序员宅基地

技术标签: 好好学习  mysql  # 数据库  数据库  b树  

博客主页:看看是李XX还是李歘歘 

每天分享一些包括但不限于计算机基础、算法等相关的知识点

点关注不迷路,总有一些知识点是你想要的

️今天的内容是      MySQL的索引结构为什么是B+树?    ️

先来看一下树的演化:

  1. :非线性结构,每个节点有唯一的一个父结点和多个子结点(子树),为一对多的关系。
  2. 二叉树:每个结点最多有两颗子树,并且子树有左右之分,不能颠倒。
  3. 满二叉树:每一层的结点个数都达到了当层能达到的最大结点数。
  4. 完全二叉树:除了最下面一层之外,其余层的结点个数都达到了当层能达到的最大结点数,且最下面一层只从左至右连续存在若干结点,而这些连续结点右边的结点全部不存在。

  5. 二叉查找树(BST)是一种特殊的二叉树,又称为二叉排序树二叉搜索树。二叉査找树的递归定义如下:

    ①要么二叉査找树是一棵空树。

    ②要么二叉查找树由根结点、左子树、右子树组成,其中左子树和右子树都是二叉查找树,且左子树上所有结点的数据域均小于或等于根结点的数据域,右子树上所有结点的数据域均大于根结点的数据域。

  6. 平衡二叉树(AVL树),是一种特殊的二叉排序树,其左右子树都平衡二叉树,且左右子树高度之差不大超过1。

  7. B树属于多叉树,又名平衡多路查找树,查找路径有多个,一个树节点中包含多条数据,并包含多个指针域。B-树就是B树(别讲什么B减树,‘-’是分隔符)。

  8. B+树,也是一种平衡多路查找树,是在B树的基础上发展而来的。

正文

数据库的索引及其数据是存储在磁盘中的,从磁盘中读取数据的速度会比内存中读取慢很多,所以,我们应当尽量减少从磁盘中读取数据的次数。 另外,从磁盘中读取数据时,都是按照磁盘块来读取的,并不是一条一条的读。 如果我们能把尽量多的数据放进磁盘块中,那一次磁盘读取操作就会读取更多数据,那我们查找数据的时间也会大幅度降低。

为什么不使用二叉查找树?

二叉查找树可能出现“一条龙”的景象,把二叉树特殊化为一个链表,相当于全表扫描,查找元素发挥不了二叉排序树的优势,只能按照链表的形式查找,高度太高了,查找效率不稳定

为什么不使用平衡二叉树?

平衡二叉树解决了二叉树高度太高,查找效率不稳定的问题。但是,平衡二叉树的每个节点只存储一个键值和数据,如果数据非常的多(大多数情况下数据是海量的),二叉树的结点将会非常多,高度也会及其高,查找效率降低。

为什么不使用B树?

B树相对于平衡二叉树,优势在于每个节点存储了更多的键值(key)和数据(data),并且每个节点拥有更多的子结点,高度就会降低,B树在提高了IO性能的同时并没有解决元素遍历效率低下的问题,在找数据时需要遍历整个B树,为解决这个问题引出了B+树,。

B+树

1. B+树非叶子节点上是不存储数据的,仅存储键值,而B树节点中不仅存储键值,也会存储数据。数据库中页的大小是固定的,innodb中页的默认大小是16KB。如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找数据进行磁盘的IO次数会再次减少,数据查询的效率也会更快。另外,B+树的阶数是等于键值的数量的,如果我们的B+树一个节点可以存储1000个键值,那么3层B+树可以存储1000×1000×1000=10亿个数据。一般根节点是常驻内存的,所以一般我们查找10亿数据,只需要2次磁盘IO。 

2. 因为B+树索引的所有数据均存储在叶子节点,并用链表链接成一个线性表【在数据库设计中B+树中各个页之间是通过双向链表连接的,叶子节点中的数据是通过单向链表连接的】。而且数据是按照顺序排列的。那么B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。而B树因为数据分散在各个节点,要实现这一点是很不容易的。  

为什么MySQL选择B+树做索引

1、B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。

2、B+树的查询效率更加稳定:由于非叶子结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

3、B+树更便于遍历:由于B+树的数据都存储在叶子结点中,非叶子结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。

4、B+树更适合基于范围的查询:B树在提高了IO性能的同时并没有解决元素遍历的我效率低下的问题,正是为了解决这个问题,B+树应用而生。B+树只需要去遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作或者说效率太低。

【数据库】B树、B+树、索引_皮皮要HAPPY的博客-程序员宅基地_数据库索引b树和b+树

MySQL中存储索引用到的数据结构是B+树,B+树的查询时间跟树的高度有关,是log(n),如果用hash存储,那么查询时间是O(1)。既然hash比B+树更快,为什么mysql用B+树来存储索引呢?

  1. 从内存角度上说,数据库中的索引一般时在磁盘上,数据量大的情况可能无法一次性装入内存,B+树的设计可以允许数据分批加载。
  2. 从业务场景上说,如果只选择一个数据那确实是hash更快,但是数据库中经常会选中多条这时候由于B+树索引有序,并且又有链表相连,它的查询效率比hash就快很多了,hash还需要解决冲突。

Hash索引和B+树区别是什么?你在设计索引是怎么抉择的?

  • B+树可以进行范围查询,Hash索引不能。
  • B+树支持联合索引的最左侧原则,Hash索引不支持。
  • B+树支持order by排序,Hash索引不支持。
  • Hash索引在等值查询上比B+树效率更高。
  • B+树使用like进行模糊查询的时候,like后面(比如%开头)的话可以起到优化的作用,Hash索引根本无法进行模糊查询。

问题2:既然增加树的路数可以降低树的高度,那么无限增加树的路数是不是可以有最优的查找效率?

答:这样会形成一个有序数组,文件系统和数据库的索引都是存在硬盘上的,并且如果数据量大的话,不一定能一次性加载到内存中。有序数组没法一次性加载进内存,这时候B+树的多路存储威力就出来了,可以每次加载B+树的一个结点,然后一步步往下找。

在内存中,红黑树比B树更优,但是涉及到磁盘操作B树就更优了

TODO:差一个红黑树

参考:
再有人问你为什么MySQL用B+树做索引,就把这篇文章发给她

https://segmentfault.com/a/1190000021488885

补充:

至于MongoDB为什么使用B-树而不是B+树,可以从它的设计角度来考虑,它并不是传统的关系性数据库,而是以Json格式作为存储的nosql,目的就是高性能,高可用,易扩展。首先它摆脱了关系模型,上面所述的优点2需求就没那么强烈了,其次Mysql由于使用B+树,数据都在叶节点上,每次查询都需要访问到叶节点,而MongoDB使用B-树,所有节点都有Data域,只要找到指定索引就可以进行访问,无疑单次查询平均快于Mysql(但侧面来看Mysql至少平均查询耗时差不多)。 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_42410605/article/details/122517769

智能推荐

ZYNQ PCIe EP实现DMA+Linux交互,非常简洁的程序_c++ 往pcie发送数据-程序员宅基地

文章浏览阅读1w次,点赞8次,收藏120次。ZYNQ PCIe-DMA源码 例程 PS-PL交互 linux/裸机 verilog C/C++ZYNQ PCIe-DMA的实现过程一、概述二、基础知识三、系统总框架四、工作原理与工作模式五、接口时序六、资源使用情况七、PS-PL交互以及测试程序ZYNQ PCIe-DMA的实现过程近期在网上淘来个源码,看了之后觉得还不错。完全刷新我对ZYNQ的认知啊,原来ZYNQ也可以这么玩的。PS-PL交..._c++ 往pcie发送数据

Python-Django毕业设计员工宿舍管理系统(程序+Lw)_用python设计一个宿舍管理系统,要求能实现寝室信息的增加、删除、修改、查询以及-程序员宅基地

文章浏览阅读173次。该项目含有源码、文档、程序数据库、配套开发软件、软件安装教程项目运行环境配置:Pychram社区版py项目技术:django + python+ Vue 等等组成,B/S模式 +pychram管理等等。环境需要1.运行环境:最好是python3.7.7,我们在这个版本上开发的。其他版本理论上也可以。2.pycharm环境:pycharm都可以。推荐pycharm社区版;3.mysql环境:建议是用5.7版本均可。_用python设计一个宿舍管理系统,要求能实现寝室信息的增加、删除、修改、查询以及

linux使用apache搭建http服务器(文件服务器)_linux怎么搭http apache服务器-程序员宅基地

文章浏览阅读8.4k次,点赞5次,收藏41次。一、安装Apache$ sudo apt-get install apache2二、修改服务器访问端口Apache2的默认访问端口为80,可修改为其他端口(当端口被占用时需要更改其访问端口)进入apache2的安装目录 /etc/apache2/,修改ports.conf文件$ cd /etc/apache2/$ sudo chmod 775 ports.conf$ vim po..._linux怎么搭http apache服务器

逆转广义表_将广义表(a,( (b, c),( ) ),( ( ( d ), e ),f) 逆转为 ((f,(e-程序员宅基地

文章浏览阅读898次。题目请编写递归算法, 逆转广义表中的数据元素。例如: 将广义表:(a,((b,c),()),(((d),e),f))逆转为:((f,(e,(d))),((),(c,b)),a)。代码#include <iostream>#include <cstring>#include <algorithm>using namespace std;void reverse_str(char *s, int l, int r){ int n = r-l; _将广义表(a,( (b, c),( ) ),( ( ( d ), e ),f) 逆转为 ((f,(e ,( d)),( ( ),(c,b), a)的代码

uniapp引入阿里云短信业务_uni-id-pages 接阿里云短信包-程序员宅基地

文章浏览阅读1.3k次。主要分为3大部分1.配置阿里云短信业务2.uniapp手机登录模块设计以及信息提交3.后端接收手机登录信息,反馈登录结果第一步可以直接参考博主Axn_很优秀的文章,申请获取到key和secrethttps://blog.csdn.net/qq_36802111/article/details/82561276?ops_request_misc=%257B%2522request%255Fid%252..._uni-id-pages 接阿里云短信包

parity密码-程序员宅基地

文章浏览阅读51次。usernode0转载于:https://www.cnblogs.com/xiaocongcong888/p/9835823.html_parity rsa

随便推点

基于 Python 深度学习的车辆特征分析系统,附源码_pycharm实时检测车辆及源码-程序员宅基地

文章浏览阅读1.7k次,点赞25次,收藏29次。而在机动车的自动识别过程中,通过利用深度学习的算法来让计算机通过不断地获取信息要素形成信息库,可以更好的提升计算机对于车辆的识别能力。本次就是通过利用了深度学习技术结合Python开发工具来设计一款能够在线通过图片分析来识别车辆的品牌的软件。_pycharm实时检测车辆及源码

matlab采样点数傅里叶变换,【 MATLAB 】模拟信号采样及离散时间傅里叶变换(DTFT)案例分析...-程序员宅基地

文章浏览阅读1.1k次。中使用的模拟信号: 为了研究在频域数量上的采样效果,对该信号使用两种不同的采样频率采样。a. 在 fs = 5000 对信号进行采样,求出并画出其离散时间傅里叶变换;b. 在 fs = 1000 对信号采样,求出并画出其离散时间傅里叶变换。题解:上篇博文也分析了,信号的带宽为2kHz,奈奎斯特频率就为 4000 样本/s,它小于第一问给出的采样频率,所以频谱混叠几乎不存在。我们通过MATLAB验证..._采样点时间轴变换matlab

程序员的选择-程序员宅基地

文章浏览阅读117次。程序员的15种选择前端程序员后端程序员全栈工程师运维工程师移动端开发工程师自由职业程序员测试工程师图像处理工程师游戏开发工程师交互体验工程师量化交易工程师数据科学家& 数据工程师研究型工程师创业公司程序员持续学习程序员转载于:https://www.cnblogs.com/huameixiao/p/11571598.html..._c程序员刚入门接触闭源和开源

vue 图片:src字符串拼接路径无效问题_vue 图片 字符串 拼接-程序员宅基地

文章浏览阅读2.1k次。无效代码:<img :src="'../../../../static/Hongkong1/img/commodity/' + oneArticleData.icon_name" />改为使用require获取图片编码即可<img :src="require('../../../../static/Hongkong1/img/commodity/' + oneArticl..._vue 图片 字符串 拼接

Notes Sixth day-渗透攻击-红队-打入内网_打入目标内网-程序员宅基地

文章浏览阅读3.5k次,点赞4次,收藏23次。**Notes Sixth day-渗透攻击-红队-信息收集(dayu)**作者:大余时间:2020-09-22请注意:对于所有笔记中复现的这些终端或者服务器,都是自行搭建的环境进行渗透的。我将使用Kali Linux作为此次学习的攻击者机器。这里使用的技术仅用于学习教育目的,如果列出的技术用于其他任何目标,我概不负责。我必须再重申一遍:务必不要做未授权测试!不要未经授权在真实网络环境中复现任何本书中描述的攻击。即使是出于好奇而不是恶意,你仍然会因未授权测试行为而陷入很多麻烦。为了个人能更好的继_打入目标内网

selenium中hidden或者是display = none的元素定位到但是不可以操作怎么办?-程序员宅基地

文章浏览阅读3.2k次。1、selenium中hidden或者是display = none的元素定位到但是不可以操作怎么办?@FindBy(id = "bs3Select") public WebElement 状态;查询条件“状态“是多选查询,但是这个元素是隐藏的,即style="display: none;",可以获取但是点不到没查到好用的方法,最终用的一种笨方法,就是用Java将元素改为可见,操作后还原不可见..._selenium is hidden 怎么处理

推荐文章

热门文章

相关标签