MySQL 索引底层数据结构实现

文章目录

  • 概述
  • 讨论范围
  • 查询数据结构
    • 查询数据结构种类及其高性能查询原理
  • MySQL 索引的底层数据结构
    • MySQL 索引的需求分析
    • 选择 MySQL 索引的底层数据结构
    • B- 树和 B+ 树的对比
    • MySQL 索引的底层数据结构揭秘

概述

MySQL 的索引是存储引擎用于快速找到记录的一种数据结构,是提升 SQL 执行效率的神器。
在正确建立及使用索引的情况下,查询性能将会有非常大的提升(从 O(N) 提升到 O(logN),几乎接近于常数级别);但在索引建立不正确或者使用不正确的情况下,将会进行全表扫描(O(N)),查询性能就比较低下了。

讨论范围

为了不给读者带来可能的理解上的偏差以及困扰,在这里首先说明,本文中讨论的索引是 MySQLInnoDB 存储引擎所使用的索引

查询数据结构

为了方便大家理解 MySQL 索引的底层数据结构,以及索引为什么能够提升查询性能,首先从查询数据结构开始讲解。
查询数据结构,光从字面上可能不太好理解。但是基于实际含义的角度上来看,或许应该叫便于查询的数据结构,又或者叫高性能的查询数据结构比较贴切。
即,查询数据结构是一种能提升数据查询效率的数据结构

查询数据结构种类及其高性能查询原理

常见的查询数据结构,有以下几种:

  • 有序数组:一个数组,数组中的元素已经全部有序。利用其有序的性质,使用二分查找可以获得 O(logN) 时间复杂度的查询效率
  • 跳表:一个链表(单或双向都可以),链表中的所有节点都有序,且在原有链表的基础上增加了一级或多级索引。利用其有序+索引性质,使用二分查找可以获得 O(logN) 时间复杂度的查询效率
  • 哈希表:一种维护了键和值的唯一映射关系的数据结构,其本质是将键通过哈希函数+解决哈希冲突的某种手段散列到数组中的一种方法。利用数组的随机访问能力,可以获得在最好情况下 O(1) 查询时间复杂度,最坏情况的时间复杂度取决于哈希函数与解决哈希冲突的方法有关。
  • 二叉搜索树:一种节点间有序的二叉树(具体定义在这里就不展开讲了)。利用其有序的性质,使用二分查找在最好情况下可以获得 O(logN) 时间复杂度的查询效率,最坏情况下为 O(N)
  • 红黑树:一种自平衡的二叉搜索树。利用其有序的性质,使用二分查找可以获得 O(logN) 时间复杂度的查询效率
  • B-B- 树,是一种自平衡的多叉搜索树。利用其有序的性质,使用二分查找可以获得 O(logN) 时间复杂度的查询效率
  • B+B+ 树,也是一种自平衡的多叉搜索树。利用其有序的性质,使用二分查找可以获得 O(logN) 时间复杂度的查询效率

可以看出,上面的数据结构,除了哈希表外,其余的数据结构都是利用了有序这个性质,并结合二分查找方法,即可获得较高的(O(N) 时间复杂度)查询效率。
唯一一个例外是二叉搜索树在最坏情况下(在节点分布极其不均匀,几乎退化成单向链表的情况下),会退化成线性搜索,其复杂度为 O(N),如下图所示:
在这里插入图片描述

可以看到,这个二叉搜索树,几乎已经退化成了一条单向链表,所以其查询时间复杂度将会是 O(N)
所以我们得出一个结论:想要提高查询效率,最好利用一个数据有序,且能自平衡(或者不需要平衡操作)的数据结构,再结合二分查找方法,即可达到目标。
在上面这个,最重要的一点就是数据必须有序,因为如果数据无序,那么二分查找也无用武之地。

MySQL 索引的底层数据结构

假设你是 MySQLInnoDB 存储引擎的开发人员,你会选择哪种数据结构作为索引底层的数据结构呢?

MySQL 索引的需求分析

想要实现一个功能,首先得分析清楚这个功能的需求是什么。现在我们想要实现 MySQL 的索引,那么索引的功能需求是什么呢?
总的来说 MySQL 的索引有以下几个需求点:

  1. 能够大幅度提升查询性能
  2. 能支持范围查询
  3. 易于维护,维护的时间复杂度应该尽可能地低
  4. 从磁盘读入内存的每个数据页应该包含尽可能多的信息
  5. 能尽可能地减少磁盘 IO 次数

选择 MySQL 索引的底层数据结构

弄清楚需求后,我们使用排除法来筛选所有可用的查询数据结构:

  • 有序数组:不能满足 3、4、5,排除。有序数组随机插入和删除元素的复杂度为 O(N),且有序数组在数据量较大时,将数据从磁盘读入内存的 IO 次数将不可控
  • 跳表:不能满足 4、5,排除。跳表与有序数组相同,从磁盘读入内存的每个数据页取决于数据本身的大小;在数据量较大时,将数据从磁盘读入内存的 IO 次数将不可控
  • 哈希表:不能满足 2,排除。哈希表不支持范围查询
  • 二叉搜索树:不能自平衡,排除
  • 红黑树:不能满足 4、5,排除。红黑树虽然能自平衡,但是在数据量较大的情况下,树的高度将会非常大,将数据从磁盘读入内存的 IO 次数也会非常多
  • B- 树:基本可以满足所有条件
  • B+ 树:可以满足所有条件

经过上面的比对,我们最终确定了 B- 树和 B+ 树两种数据结构可以满足我们的需求,那么这两种数据结构哪种更适合用于实现 MySQL 的索引呢?

B- 树和 B+ 树的对比

B- 树和 B+ 树,两者都属于自平衡的多叉搜索树。但是从细节上来说,两者之间有如下的区别:

  • B+ 树只有在叶子节点上才会携带数据,而 B- 树在每个节点上都会携带数据
    • 这个特性决定了 B+ 树在非叶子节点上存储的关键字数量越多,那么树的阶就会越大,则树中的节点就会越少,则树的高度就会越低
    • 树的高度越高,则每次查询的时候需要进行的磁盘 IO 操作就会越多
    • 树的阶越大,即非叶子节点上存储的关键字数量越多,则从磁盘读入内存的每个数据页所包含的信息数量就越多
  • B+ 树对于范围查询的性能更高
    • B+ 树的所有叶子节点组成了一个有序的链表,在进行范围查询时,只需要遍历叶子节点组成的链表就行
    • B- 树在进行范围查找时,需要反复地中序遍历,才能获得范围内的所有数据

下面的图说明了在存储同一组数据时,B- 树和 B+ 树的区别:
B-树
B+树
在这里,我们模拟 B- 树因为所有节点都要存储数据,所以阶为 3 的情况;而 B+ 树只有在叶子节点上才会存储数据,所以阶会比 B- 树要大,这里设定为 4
可以看到,在存储同一组数据时,B- 树的高度比 B+ 树要高;且 B+ 树的所有叶子节点组成了一个有序链表,范围查询时更方便也更高效。

MySQL 索引的底层数据结构揭秘

根据上面的分析,我们可以得出,要实现 MySQL 索引,底层数据结构选择 B+ 树最为合适。而实际上,MySQLInnoDB 存储引擎也确实是使用 B+ 树作为底层的数据结构的。
InnoDB 除了实现标准的 B+ 树功能外,还有以下的实现细节值得关注:

  • InnoDB 数据页的大小(由参数 innodb_page_size 决定)决定了 B+ 树的节点的大小,也决定了这个节点上存储的关键字数量
    • 默认的一个页的大小为 16KB,高度为 3B+ 树即可存储千万级别的数据量
  • 叶子节点组成的链表为双向链表,可以更方便也是更高效地处理范围查询

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/557254.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java面试——SpringMVC系列总结

文章目录: 1.什么是Spring MVC? 2.Spring MVC的主要组件有哪些? 3.请描述一下Spring MVC的工作流程? 4.MVC是什么?MVC设计模式的好处有哪些 5.拦截器Interceptor与过滤器Filter有什么区别? 6.Spring …

中蒙俄经济走廊背景_上海外国语大学师生代表团参观访问G60科创走廊俄罗斯院士创新基地...

10月23日,上海外国语大学团委书记、创新创业与实践教育学院执行院长廖文其、俄罗斯东欧中亚学院党总支副书记郝佳、辅导员石朝天及学生代表等一行15人参观访问G60科创走廊俄罗斯院士创新基地(下简称:创新基地)。创新基地主任赵磊、俄罗斯中小企业联合会华…

MySQL 索引类别与索引使用指南

文章目录概述MySQL 索引类型MySQL 索引方法BTREE 方法HASH 方法主键构成的索引结构主键索引的优点主键索引的缺点依赖顺序插入更新代价高索引使用指南索引树回顾索引树排序规则最左前缀法则最左前缀法则的产生依据最左前缀法则延申字段书写顺序不影响最左前缀法则最左前缀法则总…

测试员不可不知的几款bug管理工具

根据每个公司性质的不同,规模的不同,所用到的bug管理工具也可能不同。你们用的bug管理工具是什么呢?下面介绍几款主流的bug管理工具: 1. JIRA(付费) JIRA的生产者把JIRA定义为Professional Issue Tracker&…

Bugzilla 使用指南

本篇文章主要关注于如何高效合理的使用Bugzilla。 Bugzilla是一个开源的缺陷跟踪系统,它可以管理软件开发过程中缺陷的提交、修复、关闭等整个生命周期。 1. 基本概念 在Bugzilla中,Bug报告状态分为以下几种状态, 待确认的 unconfirmed 新…

MySQL explain 命令

概述 MySQL 的 explain 命令,主要用于查看实际查询过程中的一些执行细节(执行计划),也是查看优化器决定如何执行查询的主要方法 explain 使用示例 explain 的使用也很简单,在 select 语句之前增加 explain 关键字再…

centos6.5安装bugzilla超详细教程

经过自己的摸索,与尝试,成功在centos6.5上,安装bugzilla。并且可以发送邮件。 一、安装软件 首先,需要安装一些软件 yum install mysql-devel -y yum install mysql-server -y yum install httpd -y yum install gcc gcc-…

从numpy里加载_PyTorch强化:01.PyTorch 数据加载和处理

PyTorch提供了许多工具来简化和希望数据加载,使代码更具可读性。1.下载安装包scikit-image:用于图像的IO和变换pandas:用于更容易地进行csv解析from __future__ import print_function, divisionimport osimport torchimport pandas as pd #用…

Redmine使用手册

一、Redmine简介 Redmine是基于ROR框架开发的一套跨平台项目管理系统,是项目管理系统的后起之秀,据说是源于Basecamp的ror版而来,支持多种数据库,除了和DotProject的功能大致相当外,还有不少自己独特的功能&#xff0…

swagger2maven依赖_Maven + SpringMVC项目集成Swagger

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。作用&#x…

IDEA2019版最新配置SVN及上传教程-超详细图文详解

IDEA2019版配置SVN图文详解 1. 查看svn仓库 调出svn视图: 连接svn服务器: 连接后效果如下: 补充:如果输入正确的连接地址后出现错误—系统找不到指定的文件 请到设置中检查(File | Settings | Version Control | Subversion)SVC客户端路径…

dubbo:reference、dubbo:service和@Service、@Reference使用情况

以前在同一模块中Spring依赖注入&#xff0c;可以通过Service和Autowired Dubbo是远程服务调用&#xff0c;消费方需要注入提供方定义的接口实例&#xff0c;可以通过xml配置 dubbo:reference、dubbo:service <dubbo:service interface"fei.CustomerServices" …

SSM+Maven+Dubbo+Zookeeper简单项目实战以及易错注意点

最近为了熟悉Dubbo远程过程调用架构的使用&#xff0c;并结合SSMMaven整合了简单的一套项目实战 直接看项目结构图 各模块介绍 dubbo-common&#xff1a;存放项目需要的公众类&#xff0c;像查询模型、数据库实体模型等 dubbo-config&#xff1a;存放项目所需的公众配置文件&…

c++二叉树的层序遍历_leetcode 103. 二叉树的锯齿形层序遍历

按层次遍历&#xff0c;记录下对应节点的val和所在层&#xff0c;然后经过一定变换得到输出。python代码如下&#xff1a;# Definition for a binary tree node.# class TreeNode(object):# def __init__(self, x):# self.val x# self.left None# …

TCP和UDP的区别(Socket)

TCP和UDP区别 TCP和UDP编程区别 TCP编程的服务器端一般步骤是&#xff1a;   1、创建一个socket&#xff0c;用函数socket()&#xff1b;   2、设置socket属性&#xff0c;用函数setsockopt(); * 可选   3、绑定IP地址、端口等信息到socket上&#xff0c;用函数bind(); …

mysql open table_MySQL open table

背景&#xff1a;MySQL经常会遇到Too many open files&#xff0c;MySQL上的open_files_limit和OS层面上设置的open file limit有什么关系&#xff1f;源码中也会看到不同的数据结构&#xff0c;TABLE, TABLE_SHARE&#xff0c;跟表是什么关系&#xff1f;MySQL flush tables又…

JUC详解

JUC 前言&#xff1a; 在Java中&#xff0c;线程部分是一个重点&#xff0c;本篇文章说的JUC也是关于线程的。JUC就是java.util .concurrent工具包的简称。这是一个处理线程的工具包&#xff0c;JDK 1.5开始出现的。下面一起来看看它怎么使用。 一、volatile关键字与内存可见…

抓包工具,知道手机app上面使用的接口是哪个

fiddler。大家可以百度上面好多选择一个安装。这里随便扔一个 在电脑上安装以后。你再配置手机上的一些设置。 首先保证手机和电脑在同一个局域网上&#xff0c;连得wifi域名前面一样的&#xff0c;在电脑的cmd输入ipconfig 然后打开手机的设置。wifi页面点开查看你连的wifi的…

munin mysql_munin 监控 mysql 2种方法

munin自带的有mysql监控功能&#xff0c;但是没有启用。试了二种方法&#xff0c;都可以监控mysql。一&#xff0c;安装munin mysql的perl扩展# yum install perl-Cache-Cache perl-IPC-ShareLite perl-DBD-MySQL二&#xff0c;为监控创建mysql用户mysql> CREATE USER munin…

使用fiddler实现手机抓包

使用fiddler实现手机抓包 手机上无法直接查看网络请求数据&#xff0c;需要使用抓包工具。Fiddler是一个免费的web调试代理&#xff0c;可以用它实现记录、查看和调试手机终端和远程服务器之间的http/https通信。 一、PC端fiddler配置 1. 安装HTTPS证书 手机上的应用很多涉及…