MySQL - 深入解析MySQL索引数据结构

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
全局流量管理 GTM,标准版 1个月
简介: MySQL - 深入解析MySQL索引数据结构

MySQL官方对索引定义:是存储引擎用于快速查找记录的一种数据结构。需要额外开辟空间和数据维护工作。

  • 索引是针对表来说的,不是针对数据库来说的(建表的sql语句中的index就是索引);
  • 索引是物理数据页存储,在数据文件中(InnoDB,ibd文件),利用数据页(page)存储;
  • 索引可以加快检索速度,但是同时也会降低增删改操作速度,索引维护需要代价。

先介绍一款可以帮助理解数据结构的网站:Data Structure Visualizations

1. 索引的数据结构演进

1.1 链表

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

有一张用户表,有id、username、password三个字段。现在对这个表进行查询。

假设上表中的数据存储在链表上,执行以下SQL我们可以发现影响查询速度的是这条数据在第几行

-- 查找1次
select * from user where password = 123;
-- 查找2次
select * from user where password = 234;
-- 查找3次
select * from user where password = 78;
-- 查找4次
select * from user where password = 567;
-- 查找5次
select * from user where password = 70;
-- 查找6次
select * from user where password = 379;

假设表中有1000万条数据,现在要查询第1000万条数据,这样就需要查找1000万次。顺序查找的问题是存储数据的结构是线性的,也就是说想要查询第2条数据,我需要知道第1条数据是什么。 大家可能会考虑到为什么不要数组,直接通过下标就可以查到数据,问题是数组是固定长度的,那么数组长度定义为多少合适呢?

1.2 二叉树

要解决链表的问题,我们可以用来解决,先来看一下二叉树:二叉树是一种特殊的树,每个节点最多有两个子节点,值从左到右依次递增。

二叉搜索树通过增加了一条搜索路径,提高了查询效率,查找的效率取决于树的深度(高度)

  • 问:为什么索引的数据结构不用二叉树?

因为当值依次递增插入时,二叉树会退化成链表,对加快查询没有任何作用。

时间复杂度(代码执行的次数):O(N)

1.3 红黑树(自平衡二叉查找树)

特点:

  1. 每个节点只能是红色或黑色;
  2. 跟节点必须是黑色;
  3. 红色的节点,它的叶节点只能是黑色;
  4. 从任一节点到其叶子节点的所有路径都包含相同数目的黑色节点。

为了解决二叉树变成链表的问题,出现了红黑树。当数据插入时,红黑树通过旋转和变色来达到平衡。这样就弥补了二叉树退化成链表的尴尬。 平衡后树的高度就变成了4层,相比于二叉树,效率更高。

  • 问:为什么索引的数据结构不用红黑树?

因为当值依次递增插入时树的高度会变得特别高。就例如上图查询0009只用4次,那查询1000万呢?树的高度大概是24,最坏的情况需要查找24次!查找24次是概念呢?,MySQL存储数据是存文件的,每次查找都需要读一次文件到内存,即最坏的查询情况需要读24次文件到内存,也就是24次IO操作,这是非常耗时的。

时间复杂度为:O(log2N)

1.4 B树(多路平衡搜索树)

特点:

  1. 索引值和data数据分布在整棵树结构中
  2. 每个节点可以存放多个索引值及对应的data数据
  3. 树节点中的多个索引值从左到右升序排列

B树的搜索:从根节点开始,对节点内的索引值序列采用二分法查找,如果命中就结束查找。没有命中会进入子节点重复查找过程,直到所对应的的节点指针为空,或已经是叶子节点了才结束。

因为树的高度问题,出现了B树(多路平衡搜索树),B树的思路是多叉树。只要分叉越多,那么每一层可以存放的元素就越多,树的层级自然而然就会降低。那么分叉肯定是越多越好,最多可以多到什么程度呢?这取决于MySQL一页可存储的数据量是多少,我们可以通过SQL命令来查询:

show global status like 'Innodb_page_size';

可以看到MySQL默认一页是16384字节,大约是16kb。假设一条数据1KB为例,一颗高度为3的B树,可以存储的数据个数是 16 * 16 * 16 = 4096

问:为什么索引的数据结构不用B树?

虽然B树相对于红黑树,树的高度降低了,但是随着数据量的增多,树的高度还是会变得很高,效率会变得特别低。而且对范围查找也不方便。

1.5 B+树

特点:

  1. 非叶子节点不存储data数据,只存储索引值,这样便于存储更多的索引值
  2. 叶子节点包含了所有的索引值和data数据
  3. 叶子节点用指针连接,提高区间的访问性能

相比B树,B+树进行范围查找时,只需要查找定位两个节点的索引值,然后利用叶子节点的指针进行遍历即可。而B树需要遍历范围内所有的节点和数据,显然B+Tree效率高。

1.6 哈希

Hash 底层实现是由 Hash 表来实现的,是根据键值 <key, value> 存储数据的结构。非常适合根据key查找 value 值,也就是单个 key 查询,或者说等值查询。其结构如下所示:

从上面结构可以看出,Hash索引可以方便的提供等值查询,但是对于范围查询就需要全表扫描了。Hash索引在MySQL 中Hash结构主要应用在Memory原生的Hash索引 、InnoDB 自适应哈希索引。

InnoDB提供的自适应哈希索引功能强大,接下来重点描述下InnoDB 自适应哈希索引。

InnoDB自适应哈希索引是为了提升查询效率,InnoDB存储引擎会监控表上各个索引页的查询,当InnoDB注意到某些索引值访问非常频繁时,会在内存中基于B+Tree索引再创建一个哈希索引,使得内存中的 B+Tree 索引具备哈希索引的功能,即能够快速定值访问频繁访问的索引页。

InnoDB自适应哈希索引:在使用Hash索引访问时,一次性查找就能定位数据,等值查询效率要优于B+Tree。

自适应哈希索引的建立使得InnoDB存储引擎能自动根据索引页访问的频率和模式自动地为某些热点页建立哈希索引来加速访问。另外InnoDB自适应哈希索引的功能,用户只能选择开启或关闭功能,无法进行人工干涉。

show engine innodb status \G; 
show variables like '%innodb_adaptive%';

2. 总结

  • 为什么mysql使用的是B+树

准确的表述:为什么mysql的InnoDB和MyISAM存储引擎的索引使用的是B+树

  1. hash表,等值查询是很快的,但是不满足常用的范围查找且相邻的两个值之间没有关系,而且hash比较消耗内存。
  2. 二叉树/平衡二叉树/红黑树等都是有且仅有2个分支,共性就是数据量大的时候树的深度变深,增加IO的次数。
  3. B树会在节点上存储数据,这样一页存放的key的数量就会减少,增加树的深度。
  4. B+树中非叶子节点去除了数据,这样就会页中key的数量,而且叶子节点之间是通过链表相连,有利于范围查找和分页。
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
27天前
|
存储 关系型数据库 MySQL
阿里面试:为什么要索引?什么是MySQL索引?底层结构是什么?
尼恩是一位资深架构师,他在自己的读者交流群中分享了关于MySQL索引的重要知识点。索引是帮助MySQL高效获取数据的数据结构,主要作用包括显著提升查询速度、降低磁盘I/O次数、优化排序与分组操作以及提升复杂查询的性能。MySQL支持多种索引类型,如主键索引、唯一索引、普通索引、全文索引和空间数据索引。索引的底层数据结构主要是B+树,它能够有效支持范围查询和顺序遍历,同时保持高效的插入、删除和查找性能。尼恩还强调了索引的优缺点,并提供了多个面试题及其解答,帮助读者在面试中脱颖而出。相关资料可在公众号【技术自由圈】获取。
|
9天前
|
监控 关系型数据库 MySQL
MySQL自增ID耗尽应对策略:技术解决方案全解析
在数据库管理中,MySQL的自增ID(AUTO_INCREMENT)属性为表中的每一行提供了一个唯一的标识符。然而,当自增ID达到其最大值时,如何处理这一情况成为了数据库管理员和开发者必须面对的问题。本文将探讨MySQL自增ID耗尽的原因、影响以及有效的应对策略。
32 3
|
10天前
|
存储 关系型数据库 MySQL
MySQL 字段类型深度解析:VARCHAR(50) 与 VARCHAR(500) 的差异
在MySQL数据库中,`VARCHAR`类型是一种非常灵活的字符串存储类型,它允许存储可变长度的字符串。然而,`VARCHAR(50)`和`VARCHAR(500)`之间的差异不仅仅是长度的不同,它们在存储效率、性能和使用场景上也有所不同。本文将深入探讨这两种字段类型的区别及其对数据库设计的影响。
24 2
|
14天前
|
存储 关系型数据库 MySQL
PHP与MySQL动态网站开发深度解析####
本文作为技术性文章,深入探讨了PHP与MySQL结合在动态网站开发中的应用实践,从环境搭建到具体案例实现,旨在为开发者提供一套详尽的实战指南。不同于常规摘要仅概述内容,本文将以“手把手”的教学方式,引导读者逐步构建一个功能完备的动态网站,涵盖前端用户界面设计、后端逻辑处理及数据库高效管理等关键环节,确保读者能够全面掌握PHP与MySQL在动态网站开发中的精髓。 ####
|
21天前
|
存储 消息中间件 NoSQL
Redis数据结构:List类型全面解析
Redis数据结构——List类型全面解析:存储多个有序的字符串,列表中每个字符串成为元素 Eelement,最多可以存储 2^32-1 个元素。可对列表两端插入(push)和弹出(pop)、获取指定范围的元素列表等,常见命令。 底层数据结构:3.2版本之前,底层采用**压缩链表ZipList**和**双向链表LinkedList**;3.2版本之后,底层数据结构为**快速链表QuickList** 列表是一种比较灵活的数据结构,可以充当栈、队列、阻塞队列,在实际开发中有很多应用场景。
|
18天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
86 1
|
22天前
|
存储 关系型数据库 MySQL
MySQL MVCC深度解析:掌握并发控制的艺术
【10月更文挑战第23天】 在数据库领域,MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种重要的并发控制机制,它允许多个事务并发执行而不产生冲突。MySQL作为广泛使用的数据库系统,其InnoDB存储引擎就采用了MVCC来处理事务。本文将深入探讨MySQL中的MVCC机制,帮助你在面试中自信应对相关问题。
70 3
|
22天前
|
缓存 关系型数据库 MySQL
MySQL执行计划深度解析:如何做出最优选择
【10月更文挑战第23天】 在数据库查询性能优化中,执行计划的选择至关重要。MySQL通过查询优化器来生成执行计划,但有时不同的执行计划会导致性能差异。理解如何选择合适的执行计划,以及为什么某些计划更优,对于数据库管理员和开发者来说是一项必备技能。
31 2
|
19天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
47 0
|
21天前
|
存储 NoSQL 关系型数据库
Redis的ZSet底层数据结构,ZSet类型全面解析
Redis的ZSet底层数据结构,ZSet类型全面解析;应用场景、底层结构、常用命令;压缩列表ZipList、跳表SkipList;B+树与跳表对比,MySQL为什么使用B+树;ZSet为什么用跳表,而不是B+树、红黑树、二叉树

推荐镜像

更多