性能优化|深入理解mysql索引数据结构与算法

本文涉及的产品
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDSClaw,2核4GB
RDS AI 助手,专业版
简介: 性能优化|深入理解mysql索引数据结构与算法

什么是索引?


在mysql中,索引就是帮助mysql快速找到某条数据的一种数据结构,它是排好序的,独立于mysql表数据之外的。


索引数据结构分为哪几种


二叉树、红黑树、Hash表、B树。


在这里我们主要介绍hash表和B树


Hash表


什么是hash?
hash是一种散列函数,通过将输入值映射为一个数值,如: hash(100) = 1,不同的hash算法,hash之后的值有可能是不同的。
Hash表是以数据映射形式存在于mysql中的,那么hash表是如何产生的呢?
当添加一条数据到表中的时候,首先会对主键进行hash,然后将这条数据存在的地址和hash值建立一个映射关系,当我们根据主键查找这条数据的时候,只需要将主键进行hash,得到hash值,最后根据hash值就可以直接定位到这条数据。所以hash算法只需要进行一次磁盘IO,查询速度是非常快的。


在这里插入图片描述在这里插入图片描述

BTree


B树又称为多叉树,它在二叉树的基础之上,划分出来多个叉,我们看下它的数据结构图示。
在这里插入图片描述


我们从图中可以看出B树具有这几种特性:
1.节点从左到右递增排序
2.每个数据节点后面都会紧跟着一个指针,该指针是指向下一级的内存地址。下一级指的是位于当前指针左右两边数值中间的数据记录所存在内存中的地址。
3.叶子节点 的指针为空
4.所有索引元素是不重复的。
5.每个索引节点都存着当前指向的记录数据(或内存地址)


B+Tree


B+树其实是B树的一个变种,它在B树的基础之上做了一些改善,将索引节点所关联的数据记录全部移到叶子节点上了,目的是为了可以存储更多的索引节点,但是却增加了索引节点的冗余,因为叶子节点包含了所有的索引节点。


在这里插入图片描述在这里插入图片描述

从图中可以看出,B+树具有以下几个特性:
1.叶子节点包含所有的索引节点
2.非叶子节点不存储数据记录
3.叶子节点之间使用指针连接,提高区间访问的便利
4.指针所指向的索引节点的最左边都是大于等于指针所在深度左边的值


mysql的b+ tree优化了什么?


我们看下mysql中的B+树长什么样子的


在这里插入图片描述在这里插入图片描述

1.增加了一个双向的指针
2.首尾节点也通过指针进行关联起来
主要目的是为了更加友好的支持索引内部的范围查找。如果不加双向链表指针,我们每次查找的时候,都要回到根节点查找,增加了磁盘IO,增加查询时间。


如何计算 B+ tree最大支持数据量


在mysql中,可以使用SHOW GLOBAL STATUS LIKE 'Innodb_page_size%'指令查找到mysql对索引节点页面大小的设置,这个参数的大小决定了我们一次性能够从磁盘盘中load出多少索引数量。
在5.7版本中Innodb_page_size 默认设置为16384,也就是16k。
我们现在计算下myssql中,如果存储引擎为innodb的话,大概能支撑多少量级的数据?
我们按照高度为3的树进行计算:


1.按照每个bigint数据类型的字段存储,每个非叶子索引节点最多需要8B
2.再加上每个索引节点后面连接的指针,指针在innodb中设置的大小为6B
3.两者加起来总共14B,所以一级节点总共能存储 16kB/14B = 1170个索引节点
4.二级节点都是从一级节点划分出来,也就是一级节点中的每个节点又能划分出1170个,所以二级节点和一级节点总共能存储11701170 = 1368900个 索引节点。
5.三级节点也就是叶子节点,叶子节点存储的是主键值+记录数据,记录数据最多为1K,这个时候主键值8B可以忽略不计了,所以每个叶子节点最多能存储16k/1k = 16条记录。
6.所以Innodb引擎结构的表中最多能支撑1170
1170*16 = 21902400 条数据,大概21亿,如果大于这个值,基本上都需要进行分库分表了,mysql建议B+树的深度最好小于3.
``


hash算法很快,为什么mysql 很少使用hash索引?


在上面说过,hash算法,在查找数据的时候只用进行一次磁盘IO,查询速度非常快,但是为什么mysql不推荐使用呢?主要有以下几个原因
1.hash冲突(占比小,因为mysql的hash算法质量比较高,造成hash冲突的概率比较低)
2.无法进行范围查询(因为hash表里面存放的是hash值,不是数据本身,所以无法进行数据的比较,如果你确定你的表中只会用到精准查找的话,则可以使用hash结构的索引)


B tree与B+ tree区别?


1.增加了双向链表,便于范围查找.
2.只有叶子节点才存储数据记录,意味着可以存储更多的索引节点.


聚集(聚簇)索引与非聚集(聚簇)索引的区别?


聚集(聚簇)索引:索引文件与数据文件是合并在一起存放的
非聚集(聚簇)索引:索引文件与数据文件是独立存放的


innodb存储引擎实现(主键和辅助键)


主键索引:
在innodb中默认使用B+ tree结构类型,存储的是聚集索引,叶子结点的data区域存储的是当前主键关联的整条记录
辅助键:
辅助键的data区域存储的是主键值,也就是说如果使用辅助键索引查询,最后还得通过主键值查找对应的记录。


myisam存储引擎的索引,不管主键还是辅建索引,data区域保存的都是所关联数据的内存地址,因为myisam是非聚集索引,索引文件和数据文件是分开存储的。


为什么Innodb表必须有主键?并且推荐使用整型 并且 自增主键?


1.为什么Innodb表必须有主键?
在innodb存储引擎表中,mysql会给主键添加聚集索引,如果没有主键,mysql则会选举表中设置了唯一索引的字段设置为主键,创建主键索引;
如果表中没有字段设置为唯一索引,则mysql会生成一个row_id,作为主键,创建主键索引。
2.为什么mysql推荐使用整形作为主键字段类型?
在组建B树的时候,mysql会按照从小到大的顺序进行组建,如果是整形数字的话,mysql则可以直接进行比较,如果是其它类型的话,mysql还得需要将值转换为ascill码,进行比较,会增加创建索引和查询的时间。
3.为什么要求是自增类型?
这是由mysql限制条件决定的:
1.mysql设置innodb的一次性读取到内存中的页大小设置为16384B,也就是每个节点最大为16k,
2.btree按照顺序从左往右排列;
在这里插入图片描述


假如现在主键不是自增的,这时候如果加入了一个新的值11,那么通过比较之后,11是需要存储在10和12之间的:
1.如果这个时候该节点已经为16k了,再加入一个数据的话,会超过mysql设置的限制,就会出现分裂,拆分成两个节点,这个操作同样会增加索引创建的时间。
2.如果按照字段设置为自增的,则不会插入比当前序号小的数据,只需要在右边继续扩充就行,不会出现节点分裂的情况。


为什么非主键索引结构叶子节点存储的是主键值 (一致性和存储空间)


1.如果存储的是具体的数据的话,会造成数据不一致的问题,因为主键索引和辅助索引会同时维护数据记录,如果有一方维护失败则会出现不一致性的问题
2.都存储具体数据的话,会造成存储空间的浪费,如果只存储主键记录的话,可以存储更多的索引记录,但是需要二次根据主键查找具体数据,以时间换空间


联合索引的底层存储结构


在这里插入图片描述在这里插入图片描述

微信搜一搜【乐哉开讲】关注帅气的我,回复【干货】,将会有大量面试资料和架构师必看书籍等你挑选,包括java基础、java并发、微服务、中间件等更多资料等你来取哦。

相关实践学习
自建数据库迁移到云数据库
本场景将引导您将网站的自建数据库平滑迁移至云数据库RDS。通过使用RDS,您可以获得稳定、可靠和安全的企业级数据库服务,可以更加专注于发展核心业务,无需过多担心数据库的管理和维护。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
6月前
|
存储 监控 算法
电脑监控管理中的 C# 哈希表进程资源索引算法
哈希表凭借O(1)查询效率、动态增删性能及低内存开销,适配电脑监控系统对进程资源数据的实时索引需求。通过定制哈希函数与链地址法冲突解决,实现高效进程状态追踪与异常预警。
288 10
|
6月前
|
算法 数据可视化 测试技术
HNSW算法实战:用分层图索引替换k-NN暴力搜索
HNSW是一种高效向量检索算法,通过分层图结构实现近似最近邻的对数时间搜索,显著降低查询延迟。相比暴力搜索,它在保持高召回率的同时,将性能提升数十倍,广泛应用于大规模RAG系统。
556 10
HNSW算法实战:用分层图索引替换k-NN暴力搜索
|
7月前
|
存储 监控 算法
企业电脑监控系统中基于 Go 语言的跳表结构设备数据索引算法研究
本文介绍基于Go语言的跳表算法在企业电脑监控系统中的应用,通过多层索引结构将数据查询、插入、删除操作优化至O(log n),显著提升海量设备数据管理效率,解决传统链表查询延迟问题,实现高效设备状态定位与异常筛选。
190 3
|
9月前
|
存储 关系型数据库 MySQL
MySQL数据库索引的数据结构?
MySQL中默认使用B+tree索引,它是一种多路平衡搜索树,具有树高较低、检索速度快的特点。所有数据存储在叶子节点,非叶子节点仅作索引,且叶子节点形成双向链表,便于区间查询。
241 4
|
9月前
|
存储 SQL 关系型数据库
MySQL 核心知识与索引优化全解析
本文系统梳理了 MySQL 的核心知识与索引优化策略。在基础概念部分,阐述了 char 与 varchar 在存储方式和性能上的差异,以及事务的 ACID 特性、并发事务问题及对应的隔离级别(MySQL 默认 REPEATABLE READ)。 索引基础部分,详解了 InnoDB 默认的 B+tree 索引结构(多路平衡树、叶子节点存数据、双向链表支持区间查询),区分了聚簇索引(数据与索引共存,唯一)和二级索引(数据与索引分离,多个),解释了回表查询的概念及优化方法,并分析了 B+tree 作为索引结构的优势(树高低、效率稳、支持区间查询)。 索引优化部分,列出了索引创建的六大原则
219 2
|
9月前
|
存储 SQL 关系型数据库
MySQL 核心知识与性能优化全解析
我整理的这份内容涵盖了 MySQL 诸多核心知识。包括查询语句的书写与执行顺序,多表查询的连接方式及内、外连接的区别。还讲了 CHAR 和 VARCHAR 的差异,索引的类型、底层结构、聚簇与非聚簇之分,以及回表查询、覆盖索引、左前缀原则和索引失效情形,还有建索引的取舍。对比了 MyISAM 和 InnoDB 存储引擎的不同,提及性能优化的多方面方法,以及超大分页处理、慢查询定位与分析等,最后提到了锁和分库分表可参考相关资料。
198 0
|
9月前
|
存储 SQL 关系型数据库
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
|
9月前
|
存储 监控 算法
基于 Python 跳表算法的局域网网络监控软件动态数据索引优化策略研究
局域网网络监控软件需高效处理终端行为数据,跳表作为一种基于概率平衡的动态数据结构,具备高效的插入、删除与查询性能(平均时间复杂度为O(log n)),适用于高频数据写入和随机查询场景。本文深入解析跳表原理,探讨其在局域网监控中的适配性,并提供基于Python的完整实现方案,优化终端会话管理,提升系统响应性能。
229 4
|
10月前
|
存储 关系型数据库 MySQL
MySQL覆盖索引解释
总之,覆盖索引就像是图书馆中那些使得搜索变得极为迅速和简单的工具,一旦正确使用,就会让你的数据库查询飞快而轻便。让数据检索就像是读者在图书目录中以最快速度找到所需信息一样简便。这样的效率和速度,让覆盖索引成为数据库优化师傅们手中的尚方宝剑,既能够提升性能,又能够保持系统的整洁高效。
309 9
|
11月前
|
机器学习/深度学习 关系型数据库 MySQL
对比MySQL全文索引与常规索引的互异性
现在,你或许明白了这两种索引的差异,但任何技术决策都不应仅仅基于理论之上。你可以创建你的数据库实验环境,尝试不同类型的索引,看看它们如何影响性能,感受它们真实的力量。只有这样,你才能熟悉它们,掌握什么时候使用全文索引,什么时候使用常规索引,以适应复杂多变的业务需求。
271 12

推荐镜像

更多
下一篇
开通oss服务