数据库之舞:MySQL 数据结构的美妙之旅

本文从数据结构角度介绍MySQL特性。先讲解二分法,接着介绍MySQL存储引擎,重点阐述InnoDB记录结构、数据页结构,以及B+树索引、MyISAM索引和二级索引。还提到Explain用于分析查询语句,最后推荐阅读《MySQL是怎样运行的》了解更多内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

前段时间看了《MySQL是怎样运行的》这本书,书中介绍了MySQL数据结构,从数据结构角度去谈MySQL的特性。写这篇博客是做个总结,以下内容需要读者对MySQL有基础的认识和掌握,同时对于数据结构有一定的了解。所以这边先会对,数据结构和二分法,做些基本的介绍。然后再讲MySQL数据,是通过哪种数据结构存储的。如果掌握了其中的数据结构,那么当中的原理就掌握了。一些特性,索引,优化。就自然而然的理解了。变得非常简单。
套用《道德经》里的话就是

技术分为两种,具体的做事方法是术,做事的原理和原则是道。

二分法

因为后面要介绍的MySQL数据结构,很多地方要用到二分法,这边单独拿出来讲一遍。

小时候,玩过的猜数字游戏
1-100范围内随机选择一个数,猜这个数字是多少。如果你猜的数比目标大,它会告诉你大了;比目标小,它会告诉你小了;等于目标告诉你答对了。如何在最少次数获得答案

那时候,我们就知道猜数字。要对半猜,这样猜的速度最快。以上如果方法,学名就叫做二分法。
我们看下官方介绍:

二分法的基本思想是,将数组或列表分成两部分,判断目标元素在哪一部分中,然后继续在该部分中进行查找,直到找到目标元素或确定目标元素不存在为止。

二分法适用于有序数组或有序列表中,时间复杂度O(log n)

    public static int search(int[] a, int target) {
   
   
        int lo = 0;
        int hi = a.length - 1;
        while (lo <= hi) {
   
   
            System.out.println(String.format("lo=%s,hi=%s", lo, hi));
            int mid = lo + (hi - lo) / 2;
            if (a[mid] > target) {
   
   
                hi = mid - 1;
            } else if (a[mid] < target) {
   
   
                lo = mid + 1;
            } else {
   
   
                return mid;
            }
        }
        return -1;
    }

以上是最基础的,还有两种变形:owerBound(下界)upperBound(上界)

    //   Lower Bound(下界): Lower Bound 是指在已排序数组中,比目标值大的第一个元素的位置索引。也可以说是第一个大于等于目标值的元素的位置索引。
//   如果数组中存在多个相同目标值,则返回最左边的位置
    public static int lowerBound(int[] a, int target) {
   
   
        int lo = 0;
        int hi = a.length;
        while (lo < hi) {
   
   
            int mid = lo + (hi - lo) / 2;
            if (a[mid] < target) {
   
   
                lo = mid + 1;
            } else {
   
   
                hi = mid;
            }
        }
        return lo;
    }

    //    Upper Bound(上界): Upper Bound 是指在已排序数组中,比目标值大的第一个元素的位置索引。也可以说是第一个大于目标值的元素的位置索引。
//    如果数组中存在多个相同目标值,则返回最左边的大于目标值的位置。
    public static int upperBound(int[] a, int target) {
   
   
        int lo = 0;
        int hi = a.length;
        while (lo < hi) {
   
   
            int mid = lo + (hi - lo) / 2;
            if (a[mid] <= target) {
   
   
                lo = mid + 1;
            } else {
   
   
                hi = mid;
            }
        }
        return lo;
    }

以上变体思想,再接下来会使用到,大家可以先品味一下。如果不是很理解,那么可以将代码执行下。

数据结构 优点 缺点 特性 访问时间复杂度 插入时间复杂度
数组 - 快速随机访问 - 固定大小,不灵活 - 连续存储 O(1) O(n)
链表 - 动态大小 - 随机访问慢 - 灵活插入、删除 O(n) O(1)
- 后进先出 - 仅允许在栈顶插入和删除 - 递归、表达式求值 O(1) O(1)
队列 - 先进先出 - 随机访问慢 - 广度优先搜索、任务调度 O(n) O(1)
- 分层结构 - 平衡维护复杂 - 二叉树、二叉搜索树 O(log n) O(log n)
- 高效的插入、删除 - 不支持随机访问 - 最大堆、最小堆 O(log n) O(log n)
哈希表(散列表) - 快速的插入、删除、查找 - 内存消耗相对较大 - 高效的散列函数、冲突处理 O(1) O(1)
二叉搜索树(Binary Search Tree) - 查找、插入和删除操作的时间复杂度为O(log n) - 会退化成O(n) - 左子树中的所有节点都小于根节点,右子树中的所有节点都大于根节点 O(m) O(m)
红黑树(Red-Black Tree) - 自平衡,保持搜索效率 - 相对复杂的实现 - 高效的搜索、插入、删除 O(log n) O(log n)
B树(B-Tree) - 高度平均性能,适用于大数据集 - 不适用于小数据集 - 多叉搜索树 O(log n) O(log n)
B+树(B+ Tree) - 顺序访问性能好 - 节点拆分和合并操作相对复杂 - 子节点形成了一个有序链表 O(log n) O(log n)

B树和B+树,大家可能会比较陌生,接下来的内容又比较重要。这边做个简单介绍。

特性 B树 B+树
结构 所有节点都存储数据和关键字 非叶子节点只存储关键字,叶子节点存储数据
查找效率 略低,因为非叶子节点不包含全部关键字 高,由于非叶子节点不包含全部关键字
范围查询 低效,需要在非叶子节点和叶子节点之间遍历 高效,叶子节点形成有序链表,支持范围查询
插入和删除操作 相对复杂,可能导致树的失衡 相对稳定,树的平衡性较好
节点利用率 低,因为非叶子节点存储关键字和数据 高,由于非叶子节点只存储关键字
适用场景 适用于内存和外存储 主要用于外存储,如数据库索引、文件系统
节点拆分和合并操作 相对频繁 相对较少
删除记录时性能 略高 略低
数据检索和迭代效率 相对低效 高效,有序链表可支持顺序遍历

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

图片来源于网络

对于B树和B+树介绍,可以参考平衡二叉树、B树、B+树、B*树 理解其中一种你就都明白了这篇博文

MySQL简介

MySQL客户端请求服务器的过程:
连接管理:
	建立连接: 客户端通过TCP/IP协议与MySQL服务器建立连接。连接过程中,客户端和服务器协商通信协议版本、认证方式等信息。
	握手阶段: 服务器发送握手数据包,包含服务器版本、连接ID等信息。客户端接收握手数据包并回应,选择认证方式。
	
认证阶段:
	身份验证: 客户端发送身份验证信息,通常是用户名和密码等。服务器验证信息的合法性,如果认证通过,客户端获得访问权限。
	
查询缓存:
	查询缓存检查: 服务器在接收到客户端的查询请求后,会检查查询缓存,看是否已经缓存了相同的查询。如果在缓存中找到了相同的查询,服务器直接返回缓存结果,而不执行实际查询。
	
语法解析:
	解析SQL语句: 服务器对客户端发送的SQL语句进行语法解析,确保语法正确。如果语法错误,服务器返回错误信息。
查询优化:
	查询优化器: 服务器使用查询优化器分析查询语句,确定最佳执行计划。这涉及索引的选择、连接顺序等优化步骤。
	
存储引擎:
	执行计划: 优化后的查询计划交给存储引擎层执行。存储引擎负责管理表、索引,并执行具体的读取、写入操作。
	
结果返回:
	结果传输: 存储引擎返回执行结果给服务器,服务器将结果传递给客户端。结果可以是查询结果集、执行状态信息等。
	
断开连接:
	关闭连接: 当客户端不再需要与服务器通信时,可以选择主动断开连接。客户端发送断开连接请求,服务器关闭连接。如果是持久连接,可以选择保持连接以便后续的请求。

存储引擎是数据库管理系统(DBMS)中的一个关键组件,负责管理数据的存储、检索和索引等操作。存储引擎定义了数据库系统如何组织、存储和操作数据,决定了数据库的性能、事务支持、并发控制和其他关键特性。

常见的MySQL存储引擎:
InnoDBInnoDBMySQL的默认存储引擎,提供了ACID事务支持、行级锁、外键约束等特性。支持事务、行级锁、外键,适合并发,**数据存储方式是按照主键顺序存储**

MyISAMMyISAMMySQL的另一个常见的存储引擎,它不支持事务和行级锁,但具有较高的性能和较小的存储开销。MyISAM适用于读密集型应用,如数据仓库和日志分析。按照插入顺序存储;

MEMORYMEMORY存储引擎将表数据存储在内存中,提供了非常快速的数据访问速度,但在数据库关闭时数据会丢失。适用于小型临时表或缓存数据。相当于Redis

NDB ClusterNDB Cluster存储引擎是MySQL Cluster的一部分,提供高可用性和分布式数据库功能,适用于需要水平扩展的分布式应用。

CSVCSV存储引擎以纯文本形式存储数据,适用于数据交换或导出。

ArchiveArchive存储引擎专注于高度压缩的数据存储,适用于大量历史数据的存储。

在上面的存储引擎用的比较多是InnoDB和MyISAM,大家重点记得InnoDB数据存储方式是按照主键顺序存储,MyISAM按照插入顺序存储。以下内容介绍的都是InnoDB存储引擎

InnoDB记录结构

行格式

InnoDB 存储引擎支持不同的行格式,每种行格式有其自身的优势和适用场景。在 InnoDB 存储引擎中,常见的行格式包括 COMPACT、REDUNDANT、DYNAMIC(默认) 和 COMPRESSED。
行格式就是我们存储的每一条记录,一条记录就是一行。那么这条记录长什么样。

行格式 描述 适用场景
COMPACT 默认的行格式,压缩存储数据,提高性能和空间效率。 适用于不包含太多变长列的表。
REDUNDANT 旧版行格式,包含冗余信息,已不再推荐使用。 主要用于向后兼容。
DYNAMIC 对变长列进行动态存储,适用于包含大量变长列的表。 适用于具有许多变长列的表。
COMPRESSED 压缩行格式,通过 zlib 压缩算法减小存储空间。 适用于 I/O 受限的环境,提高性能。

在这里插入图片描述

COMPACT 格式

这边介绍的是COMPACT 格式,COMPACT 和DYNAMIC相差不多。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值