存储引擎

存储引擎是数据库管理系统(DBMS)或键值存储系统的核心组件,它定义了数据在持久化存储介质上如何组织、存储、检索和管理。不同的存储引擎针对特定负载(如读密集型、写密集型、混合型)和数据模型(如关系型、键值型、文档型)进行优化。

目前常见的存储引擎使用的存储数据结构有如下几种。

1)哈希表(Hash Table):提供O(1)平均时间复杂度的单点查询(精确键匹配)。非常适合键值(Key-Value)存储,但天然不支持范围查询或有序遍历(除非对整个数据集扫描)。

2)B+树(Balance+ Tree):为磁盘I/O优化的多路平衡搜索树。广泛用于关系型数据库(如MySQL InnoDB, PostgreSQL)的索引和数据存储。支持高效的单点查询、范围查询和有序遍历。对读密集型和混合型负载友好。

3)LSM树(Log-Structured Merge Tree):专为高写入吞吐量设计的结构。通过将随机写转换为内存中的有序写入和磁盘上的顺序批量写入来优化写性能。广泛应用于写密集型的NoSQL数据库(如Google Bigtable, Apache HBase, Cassandra, RocksDB, LevelDB)。

MySQL B+树

MySQL的存储引擎,主要分InnoDB和MyISAM。InnoDB是MySQL的默认引擎,InnoDB使用B+树存储数据。表中的数据(主键索引)和辅助索引最终都会使用 B+ 树来存储,其中前者会以 <id, row> 的方式存储,而后者会以 <index, id> 的方式进行存储。

为了分析 InnoDB 选择 B+ 树作为其索引结构的原因,可以将其与 B 树和哈希表进行对比。随着互联网的快速发展,数据存储规模已攀升至千万甚至亿级,而典型的互联网应用场景往往是读多写少。例如,热点新闻的访问、商品列表的展示以及基于价格、地理位置等条件的智能化推荐排序,都需要高效的数据查询和排序能力。因此,数据存储结构需要满足以下核心需求。

1)高效的查询性能:尤其是在范围查询和排序操作上,需要具备优异的性能表现。

2)充分利用顺序 I/O 和 Page Cache 机制:通过优化 I/O 性能,减少磁盘访问的延迟。

3)支持大规模数据存储:在保证高效查询的同时,尽可能减少写入操作的 I/O 开销。

由于哈希映射关系,哈希表在查找单条数据时候,能保证O(1)的时间复杂读。但哈希表在范围查询和排序遍历时候,只能进行全表扫描并依次判断是否满足条件。全表扫描对数据库的性能影响非常大。比如如下的SQL语句:

SELECT * FROM commodity WHERE price > 10 AND price < 100
SELECT * FROM commodity WHERE ORDER BY price DESC

平均时间复杂度比O(1)稍慢的是O(logn),这类数据结构有平衡二叉树(AVL Tree),红黑树(RB Tree)、B树(B Tree)、B+树(B+ Tree)等。他们天然就支持排序、范围查找操作。

平衡二叉树在一般情况下查询性能非常好,但平衡二叉树单个节点只能保存一个数据,因此当覆盖大量数据时候,平衡二叉树的树高度很高。这意味着当需要通过遍历获取存储在硬盘上的数据时候,需要更多次的I/O操作。硬盘读取时间远远超过数据在内存中比较的时间,这将导致程序大部分时间会阻塞在硬盘 I/O 上。

B树

跟平衡二叉树的不同是,B树是一种多叉树。阶数m决定了B树的节点大小和树的高度。较大的阶数可以容纳更多的键值对,减少树的高度和硬盘访问次数。

B树中每个节点都存放着索引和数据,从下图可见,查询索引为 50 的节点就在第一层,B树只需一次硬盘 I/O 即可完成查找。因此B树的查询最好时间复杂度是 O(1)。

B+树

B+树是B树的一种变种,它与B树的区别是:

叶子节点保存了完整的索引和数据,而非叶子节点只保存索引值。所以查询索引为 50的数据,必须要遍历到叶子节点才能取到,因此查询时间固定为 O(logn)。

常见的B+树阶数可以是100或更大,以适应硬盘上的大量数据。

数据查询

B树的范围查询,比如上图要查询“大于10小于30的数据”,需要进行4次硬盘的随机 I/O 。范围查询的随机 I/O次数不稳定和放大,也是 B 树最大的性能问题:

1)遍历根节点的第一个元素是25,大于 10。

2)遍历左子节点的元素,找到第一个大于10的数据是11。

3)重新遍历根节点,发现不包含小于30的数据。

4)遍历载右子节点的元素,找到最后一个小于30的数据是27。

而B+树叶子节点保存指向下一个叶子节点的指针,叶子节点之间类似于单链表连接起来,因此叶子节点的数据在硬盘里是顺序存储的。当读到某个叶子节点数据时候,硬盘根据局部性原理会提前将相关的数据都读进内存,这使得范围查询和排序很高效。

操作系统在读文件时,根据Page Cache机制将数据加载到页缓存中,页的默认大小是4KB。由于B+树非叶子节点都只是索引值,这就意味B+树一次I/O,相比于B树能读出的索引值更多,从而减少查询时候需要的I/O次数。

不同于操作系统,InnoDB引擎的页大小默认是16KB,如下估算:

1)非叶子节点存放(key,pointer),假设主键ID为bigint类型,长度为8字节,而指针在InnoDB源码中为6字节,一共14字节,即非叶子节点能存放 16KB/14 左右的(key,pointer)。

2)叶子节点中保存的一行记录的数据大小为1KB,大约可以存储16K/1K = 16记录数。

如果B+树高度为2,那么存放总记录数为:根节点指针数单个叶子节点记录行数 = 16KB/14 * 16 大约 1.8w+ 数据。

如果B+树高度为3,那么存放总记录数为:根节点指针数
单个叶子节点记录行数 = 16KB/14 * 16KB/14 * 16 大约2kw+数据。

数据写入

相比于数据读取场景,B+树在写密集型场景的性能并不理想。这主要原因是:B+树在写入(插入、删除、更新)时,为维持树的平衡,可能触发节点分裂、合并。这些操作可能涉及多个磁盘页的修改,导致随机I/O,且需要更新Page Cache中的对应页,使其失效。因此,在写密集型场景下,B+树性能不如专为写入优化的结构。

因此B+树也通过一些优化策略来提高写操作的性能。比如使用写缓冲区(Write Buffer)来缓存写操作,然后定期将缓冲区中的数据批量刷入硬盘,将随机I/O合并为后续的顺序I/O。此外可以使用多版本并发控制机制(MVCC)来减少写入时候的锁竞争和提高并发性能。

未完待续

很高兴与你相遇!如果你喜欢本文内容,记得关注哦!!!

十年大厂员工终明白:MySQL性能优化的尽头,是对B+树的极致理解的更多相关文章

  1. Java面试准备十六:数据库——MySQL性能优化

    2017年04月20日 13:09:43 阅读数:6837 这里只是为了记录,由于自身水平实在不怎么样,难免错误百出,有错的地方还望大家多多指出,谢谢. 来自MySQL性能优化的最佳20+经验 为查询 ...

  2. [MySQL性能优化系列]LIMIT语句优化

    1. 背景 假设有如下SQL语句: SELECT * FROM table1 LIMIT offset, rows 这是一条典型的LIMIT语句,常见的使用场景是,某些查询返回的内容特别多,而客户端处 ...

  3. mysql 性能优化方案

    网 上有不少MySQL 性能优化方案,不过,mysql的优化同sql server相比,更为麻烦与复杂,同样的设置,在不同的环境下 ,由于内存,访问量,读写频率,数据差异等等情况,可能会出现不同的结果 ...

  4. mysql 性能优化方案1

    网 上有不少mysql 性能优化方案,不过,mysql的优化同sql server相比,更为麻烦与复杂,同样的设置,在不同的环境下 ,由于内存,访问量,读写频率,数据差异等等情况,可能会出现不同的结果 ...

  5. mysql 性能优化方案 (转)

    网 上有不少mysql 性能优化方案,不过,mysql的优化同sql server相比,更为麻烦与复杂,同样的设置,在不同的环境下 ,由于内存,访问量,读写频率,数据差异等等情况,可能会出现不同的结果 ...

  6. MySQL 性能优化

    内容简介:这是一篇关于mysql 性能,mysql性能优化,mysql 性能优化的文章.网上有不少mysql 性能优化方案,不过,mysql的优化同sql server相比,更为麻烦与负责,同样的设置 ...

  7. 涨姿势:Mysql 性能优化完全手册

    涨姿势:Mysql 性能优化完全手册 深入理解MySQL服务器架构 客户端层 MySQL逻辑架构整体分为三层,最上层为客户端层,诸如:连接处理.授权认证.安全等功能均在这一层处理. 中间层 MySQL ...

  8. Mysql 性能优化教程

    Mysql 性能优化教程 目录 目录 1 背景及目标 2 Mysql 执行优化 2 认识数据索引 2 为什么使用数据索引能提高效率 2 如何理解数据索引的结构 2 优化实战范例 3 认识影响结果集 4 ...

  9. 转 Mysql性能优化教程

    Mysql性能优化教程 背景及目标 厦门游家公司(4399.com)用于员工培训和分享. 针对用户群为已经使用过mysql环境,并有一定开发经验的工程师 针对高并发,海量数据的互联网环境. 本文语言为 ...

  10. MySQL 性能优化系列之一 单表预处理

    MySQL 性能优化系列之一 单表预处理 背景介绍 我们经常在写多表关联的SQL时,会想到 left jion(左关联),right jion(右关联),inner jion(内关联)等. 但是,当表 ...

随机推荐

  1. Spring @Controller、@Component和@Autowired等几个最常见的注解

    在如今Spring Boot和Spring Cloud风生水起,Spring注解开发已成为主流开发模式,本篇将介绍常用的组件注册方式.我们所说的组件注册其实就是Spring 把合适的java类全部注册 ...

  2. Dispatch PDI v2.0.4即将发布,历经1000+用户装机验证,稳定版震撼来袭!

    Dispatch PDI V2.0.4版本,即将登场! 亲爱的用户们: 在数据调度领域的探索之路上,我们始终致力于为大家提供更强大.更高效的工具.今天,我们怀着激动的心情宣布,Dispatch PDI ...

  3. 【C语言/C++】你知道线程安全代码到底是怎么编写的吗?

    相信有很多同学在面对多线程代码时都会望而生畏,认为多线程代码就像一头难以驯服的怪兽,你制服不了这头怪兽它就会反过来吞噬你. 夸张了哈,总之,多线程程序有时就像一潭淤泥,走不进去退不出来. 可这是为什么 ...

  4. python学习课后练习

    此次爬虫学习的资源是B站所找,具体如下:Python课程天花板,Python入门+Python爬虫+Python数据分析5天项目实操/Python基础,该课程留了课后练习,我把自己的代码和想法单独整成 ...

  5. HTTP1和HTTP2的区别

    HTTP1和HTTP2的区别 一.Http1 Http1.x 缺点: 线程阻塞,在同一时间,同一域名的请求有一定数量限制,超过限制的书目录的请求会被阻塞 短连接:浏览器和服务器他只保持短暂的连接,浏览 ...

  6. Tauri2.0-DeepSeek电脑端Ai对话|tauri2+vite6+deepseek流式ai聊天系统

    重磅新作tauri2.0+vue3.5+deepseek+arco桌面客户端ai流式输出聊天对话系统. tauri2-vue3-deepseek:桌面端ai聊天对话,基于Tauri2.x+Vite6集 ...

  7. 京东正式开源Taro on HarmonyOS C-API 版本,为鸿蒙应用跨端开发提供高性能框架

    近日,京东正式开源了Taro on HarmonyOS C-API 版本,为鸿蒙应用跨端开发提供高性能框架.这次版本的发布,带来了更丰富的样式适配.更高效的渲染性能.更全面的组件支持,让开发者以Web ...

  8. 最受欢迎的三方库之harmony-utils

    harmony-utils(API12+) 简介与说明 harmony-utils 一款功能丰富且极易上手的HarmonyOS工具库,借助众多实用工具类,致力于助力开发者迅速构建鸿蒙应用.其封装的工具 ...

  9. 【FAQ】HarmonyOS SDK 闭源开放能力 —Push Kit(13)

    1.问题描述: 推送通知里的skills标签有什么用?不填写似乎不影响推送,以及推送的点击跳转操作 解决方案: 鸿蒙系统的推送通知中的skills标签主要用于指定接收推送的应用程序所支持的能力(Ski ...

  10. C# 使用Microsoft.Data.Sqlite 的一些方法 System.Data.SQLite 包加密失败

    SQLite Encryption(加密)问题_码农01号的博客-程序员宅基地 - 程序员宅基地 (cxyzjd.com) SQLite Encryption(加密)问题_码农01号的博客-程序员宅基 ...