我不得不告诉大家的MySQL优化“套路”(四)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 说起 MySQL 的查询优化,相信大家收藏了一堆奇技淫巧:不能使用 SELECT *、不使用 NULL 字段、合理创建索引、为字段选择合适的数据类型.....

理解 B+Tree 时,只需要理解其最重要的两个特征即可:

  • 所有的关键字(可以理解为数据)都存储在叶子节点(Leaf Page),非叶子节点(Index Page)并不存储真正的数据,所有记录节点都是按键值大小顺序存放在同一层叶子节点上。
  • 所有的叶子节点由指针连接。如下图为高度为 2 的简化了的 B+Tree。

32.jpg


简化 B+Tree


怎么理解这两个特征?MySQL 将每个节点的大小设置为一个页的整数倍(原因下文会介绍),也就是在节点空间大小一定的情况下,每个节点可以存储更多的内结点,这样每个结点能索引的范围更大更精确。


所有的叶子节点使用指针链接的好处是可以进行区间访问,比如上图中,如果查找大于 20 而小于 30 的记录,只需要找到节点 20,就可以遍历指针依次找到 25、30。


如果没有链接指针的话,就无法进行区间查找。这也是 MySQL 使用 B+Tree 作为索引存储结构的重要原因。


MySQL 为何将节点大小设置为页的整数倍,这就需要理解磁盘的存储原理。磁盘本身存取就比主存慢很多,再加上机械运动损耗(特别是普通的机械硬盘),磁盘的存取速度往往是主存的几百万分之一。


为了尽量减少磁盘 I/O,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存,预读的长度一般为页的整数倍。

页是计算机管理存储器的逻辑块,硬件及 OS 往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(许多 OS 中,页的大小通常为 4K)。主存和磁盘以页为单位交换数据。当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后一起返回,程序继续运行。


MySQL 巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次 I/O 就可以完全载入。


为了达到这个目的,每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现了读取一个节点只需一次 I/O。


假设 B+Tree 的高度为 h,一次检索最多需要 h-1 次 I/O(根节点常驻内存),复杂度 O(h) = O(logmN)。


实际应用场景中,M通常较大,常常超过 100,因此树的高度一般都比较小,通常不超过 3。


最后简单了解下 B+Tree 节点的操作,在整体上对索引的维护有一个大概的了解,虽然索引可以大大提高查询效率,但维护索引仍要花费很大的代价,因此合理的创建索引也就尤为重要。


仍以上面的树为例,我们假设每个节点只能存储 4 个内节点。首先要插入第一个节点 28,如下图所示:

33.jpg

leaf page 和 index page 都没有满


接着插入下一个节点 70,在 Index Page 中查询后得知应该插入到 50-70 之间的叶子节点。


但叶子节点已满,这时候就需要进行分裂的操作,当前的叶子节点起点为 50,所以根据中间值来拆分叶子节点,如下图所示:

34.jpg


Leaf Page 拆分


最后插入一个节点 95,这时候 Index Page 和 Leaf Page 都满了,就需要做两次拆分,如下图所示:

35.jpg                      Leaf Page 与 Index Page 拆分


拆分后最终形成了这样一棵树,如下图所示:


36.jpg

最终树


B+Tree 为了保持平衡,对于新插入的值需要做大量的拆分页操作,而页的拆分需要 I/O 操作,为了尽可能的减少页的拆分操作,B+Tree 也提供了类似于平衡二叉树的旋转功能。


当 Leaf Page 已满但其左右兄弟节点没有满的情况下,B+Tree 并不急于去做拆分操作,而是将记录移到当前所在页的兄弟节点上。


通常情况下,左兄弟会被先检查用来做旋转操作。就比如上面第二个示例,当插入 70 的时候,并不会去做页拆分,而是左旋操作。


37.jpg

左旋操作


通过旋转操作可以最大限度的减少页分裂,从而减少索引维护过程中的磁盘的 I/O 操作,也提高索引维护效率。


需要注意的是,删除节点跟插入节点类似,仍然需要旋转和拆分操作,这里就不再说明。


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
216 9
|
2月前
|
SQL 关系型数据库 MySQL
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
MySQL慢查询优化、索引优化,是必知必备,大厂面试高频,本文深入详解,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
|
16天前
|
SQL 关系型数据库 MySQL
MySQL派生表合并优化的原理和实现
通过本文的详细介绍,希望能帮助您理解和实现MySQL中派生表合并优化,提高数据库查询性能。
56 16
|
17天前
|
SQL 关系型数据库 MySQL
MySQL派生表合并优化的原理和实现
通过本文的详细介绍,希望能帮助您理解和实现MySQL中派生表合并优化,提高数据库查询性能。
33 7
|
4天前
|
缓存 关系型数据库 MySQL
【深入了解MySQL】优化查询性能与数据库设计的深度总结
本文详细介绍了MySQL查询优化和数据库设计技巧,涵盖基础优化、高级技巧及性能监控。
58 0
|
1月前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
82 18
|
1月前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
84 7
|
1月前
|
缓存 关系型数据库 MySQL
MySQL 索引优化与慢查询优化:原理与实践
通过本文的介绍,希望您能够深入理解MySQL索引优化与慢查询优化的原理和实践方法,并在实际项目中灵活运用这些技术,提升数据库的整体性能。
107 5
|
2月前
|
SQL 关系型数据库 MySQL
MySQL慢查询优化、索引优化、以及表等优化详解
本文详细介绍了MySQL优化方案,包括索引优化、SQL慢查询优化和数据库表优化,帮助提升数据库性能。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
MySQL慢查询优化、索引优化、以及表等优化详解
|
2月前
|
关系型数据库 MySQL Java
MySQL索引优化与Java应用实践
【11月更文挑战第25天】在大数据量和高并发的业务场景下,MySQL数据库的索引优化是提升查询性能的关键。本文将深入探讨MySQL索引的多种类型、优化策略及其在Java应用中的实践,通过历史背景、业务场景、底层原理的介绍,并结合Java示例代码,帮助Java架构师更好地理解并应用这些技术。
83 2