MySQL个人复习总结

本文深入探讨了MySQL的优化策略,包括SQL优化、索引使用、分页查询优化、事务处理、存储引擎对比(MyISAM与InnoDB)、MVCC机制等。讲解了为何不推荐使用NULL作为字段默认值,并分析了使用LIKE "%x"对索引的影响。此外,还对比了MySQL与PostgreSQL在特性、性能和适用场景上的差异。

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

最近想把MySQL的知识点再过一遍,带着自己的理解使用简短的话把一些问题总结一下,尤其是开发中和面试中的高频问题,基础知识点可以参考之前写的如下几篇博客,这篇不再赘述,阅读顺序由浅入深依次递进。

一、MySQL 概述 数据库&表操作 数据增删改
二、MySQL 单表查询 多表设计
三、MySQL 多表查询 事务 索引
四、Mybatis入门
五、Mybatis—基础操作
六、Mybatis—XML配置文件、动态SQL
七、MySQL窗口函数入门指南

目录

语法

in和exists的区别

Mysql中,in关键字用于在一个字段中匹配多个值。它的语法如下:

SELECT name
FROM students
WHERE class_id IN (101, 102, 104);

exists关键字用于检查子查询的结构是否为空。它的语法如下:

# 询至少有一个员工在工作的部门
SELECT name
FROM departments d
WHERE EXISTS (
    SELECT 1
    FROM employees e
    WHERE e.department_id = d.id
);

区别:

Mysql中的in语句是把外表和内表做hash连接(等值匹配),而exists语句是对外表做loop连接(先进行主查询,然后逐个的来进行子查询匹配结果),每次loop连接再对内表进行查询。单纯的说exists比in语句的效率高的说法其实不准确,要区分场景:

  • 如果查询的两个表大小相当,那么用in和exists区别不大;
  • 如果两个表一个较小,另一个是大表,则子查询表大的用exists,子查询小的用in;
  • not in 和 not exists:
    • 如果查询语句用了not in,那么内外表都进行全表扫描,没有用到索引;
    • 而not exists的子查询依然能用到表上的索引。所以无论哪个表大,用not exists都比not in要快。

为什么如果两个表一个较小,另一个是大表,则子查询表大的用exists,子查询小的用in,这点要从它们的工作机制解释,遵循的准则也是小表驱动大表的优化准则。

  • 在执行 IN 查询时,子查询会首先全部执行并将结果集存储在内存中。然后,主查询会将每一行数据与子查询的结果集进行比较。因此,如果子查询返回的结果集较小,而主查询的表较大,内存中的比较操作相对会比较快。
  • EXISTS 子查询在找到第一条满足条件的记录时就会立即返回 TRUE,并停止继续搜索。因此,在主查询表较大,而子查询返回的结果集也较大时,每次找到一行满足条件的数据,EXISTS 查询便能停止,而不需要将整个子查询的结果集载入内存。


drop、delete与truncate的区别

三者都表示删除,但是三者有一些差别:

delete truncate drop
类型 属于DML(数据增删改查) 属于DDL(数据库操作) 属于DDL
回滚 可回滚 不可回滚 不可回滚
删除内容 表结构还在,删除表的全部或者一部分数据行 表结构还在,删除表中的所有数据 从数据库中删除表,所有数据行,索引和权限也会被删除
删除速度 删除速度慢,需要逐行删除 删除速度快 删除速度最快

总结,在不再需要一张表的时候,用drop;在想删除部分数据行时候,用delete;在保留表而删除所有数据的时候用truncate。



HAVING和WHERE的区别

HAVING子句和WHERE子句都用于过滤数据,但它们的应用场景和时机不同:

  • WHERE子句:用于过滤行数据,发生在数据分组之前。它不能与聚合函数一起使用。
  • HAVING子句:用于过滤分组后的数据集,通常与聚合函数一起使用。


ORDER BY 排序原理

MySQL 中的 ORDER BY 排序原理

  • 1.排序缓冲区(sort-buffer):
    MySQL 在执行 ORDER BY 操作时,会为每个线程分配一个内存区域,称为 sort_buffer,其大小由sort_buffer_size 参数决定。
    如果排序所需的数据量小于 sort_buffer_size,排序操作可以在内存中完成,这样的排序称为内部排序

  • 2.内部排序的两种方式:

    • 全字段排序: MySQL 首先在索引树(通常是 B-Tree 或者 InnoDB 的聚簇索引)中找到满足条件的记录主键,然后根据主键 ID 读取完整数据,将其放入 sort_buffer,并在内存中对这些完整数据进行排序。
    • Rowid 排序(Mysql默认): 这种方式通过减少每行数据的长度来让 sort_buffer 容纳更多的行。它在排序时只保存必要的行 ID 和排序键,最后再根据行 ID 获取完整的数据。
    • 全字段排序适合在内存充足、数据量较小的情况下使用,以减少磁盘访问。Rowid 排序更适合大数据集或内存资源有限的场景,因为它能够更高效地利用内存资源,尽量避免外部排序的开销。

全字段排序优点:1.减少额外的磁盘 I/O: 排序完成后,不需要再回到磁盘读取数据,因为所有字段数据都已经在内存中。2.执行步骤简单: 一次性完成排序和数据提取,无需额外的步骤。
缺点:1.内存消耗大: 需要将每行的完整数据都加载到 sort_buffer 中,占用大量内存,容易导致内存不足。2.外部排序可能性大: 当数据量较大时,容易导致 sort_buffer 溢出,从而需要使用磁盘进行外部排序,效率降低。


Rowid 排序优点:1.内存利用率高: 只存储用于排序的字段和行指针,占用的内存较少,可以在 sort_buffer 中存储更多的行数据。2.减少外部排序: 由于内存占用少,减少了数据溢出到磁盘进行外部排序的概率,提升了整体性能。
缺点:1.增加磁盘 I/O: 排序完成后需要通过 Rowid 再次访问磁盘来获取完整数据,这可能导致额外的磁盘读写操作。2.执行步骤复杂: 排序后需要进行额外的步骤来获取完整的数据,这在高并发或大数据量时可能影响性能。

  • 3.外部排序(External Sorting):
    • 当数据量超出 sort_buffer 无法全部放入内存时,MySQL 会使用磁盘上的临时文件来辅助排序,这种方法称为外部排序
    • 外部排序通常将数据划分为多个小块,每一块数据会先在内存中排序,然后写入磁盘上的临时文件。最后,这些临时文件会通过一种称为归并排序的方式合并为一个最终的排序结果。

总结
当数据量较小时,MySQL 能够在内存中完成排序,这样效率较高。
当数据量较大时,MySQL 则会采用外部排序,将排序操作分块进行,并使用磁盘存储和归并技术来完成整个排序过程。
为了提高排序效率,MySQL 在内部排序时可以选择不同的排序策略(如全字段排序和 rowid 排序),以便尽可能地利用内存。



数据类型

MySQL常见数据类型

MySQL 提供了多种数据类型以满足不同的存储需求,主要分为数值类型、日期和时间类型,以及字符串类型。

一、数值类型

整数类型

  • TINYINT:占用 1 字节,表示的范围是 -128 到 127(有符号)或 0 到 255(无符号)。
  • SMALLINT:占用 2 字节,表示的范围是 -32,768 到 32,767(有符号)或 0 到 65,535(无符号)。
  • MEDIUMINT:占用 3 字节,表示的范围是 -8,388,608 到 8,388,607(有符号)或 0 到 16,777,215(无符号)。
  • INT 或 INTEGER:占用 4 字节,表示的范围是 -2,147,483,648 到 2,147,483,647(有符号)或 0 到 4,294,967,295(无符号)。
  • BIGINT:占用 8 字节,表示的范围是 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807(有符号)或 0 到 18,446,744,073,709,551,615(无符号)。

浮点数类型

  • FLOAT(M, D):占用 4 字节,单精度浮点数。M 表示显示总长度,D 表示小数点后的位数。
  • DOUBLE(M, D) 或 REAL:占用 8 字节,双精度浮点数。M 表示显示总长度,D 表示小数点后的位数。

定点数类型

  • DECIMAL(M, D) 或 NUMERIC(M, D):用于存储精确的定点数,通常用于财务计算。M 表示总位数,D 表示小数点后的位数。内部存储为字符串格式以保证精度。

二、日期和时间类型

  • DATE:用于存储日期,格式为 YYYY-MM-DD,表示的范围是 1000-01-01 到 9999-12-31。
  • TIME:用于存储时间,格式为 HH:MM:SS,表示的范围是 -838:59:59 到 838:59:59。
  • DATETIME:用于同时存储日期和时间,格式为 YYYY-MM-DD HH:MM:SS,表示的范围是 1000-01-01 00:00:00 到 9999-12-31 23:59:59。
  • TIMESTAMP:用于存储 Unix 时间戳,格式为 YYYY-MM-DD HH:MM:SS,表示的范围是 1970-01-01 00:00:01 UTC 到 2038-01-19 03:14:07 UTC,会受到时区影响。
  • YEAR:用于存储年份,格式为 YYYY,表示的范围是 1901 到 2155。

三、字符串类型

  • CHAR(M):定长字符串,长度最多为 255 个字符。M 指定字符串的固定长度,不足时会用空格填充。
  • VARCHAR(M):变长字符串,最大长度可达 65,535 个字符。M 指定字符串的最大长度,根据实际内容长度存储,节省空间。

最后讲一讲text和blob两种数据类型,它们的设计初衷是为了存储大数据使用的,text是文本类型,blob是二进制数据类型。text类型系列允许更大的文本存储,longtext可以存储超过 40 亿个字符(4G)。text类型的字段则可能被存储在 MySQL 的专用区域中,行中存储的是一个指针,指向实际的文本数据。由于这种分离存储,使用 TEXT 类型字段可能会有性能开销,尤其是在检索和排序时。


还有一些枚举(ENUM)、集合(SET)、空间数据、json(JSON)、位类型(BIT(M)),这里不赘述。



varchar(n)中n最大为多少

在 MySQL 中,VARCHAR(n) 类型中的 n 表示该字段最多能存储的字符数量,而不是字节大小。
MySQL 规定,一行记录(不包括 TEXT、BLOB 等大对象类型的字段)最大占用 65535 字节。这一限制不仅仅包括数据本身,还包括存储开销(storage overhead),如变长字段长度列表和 NULL 值列表。

单字段的情况
假设数据库表只有一个 VARCHAR(n) 类型的字段:

  • 字符集为 ASCII: ASCII 字符集下,每个字符占用 1 字节。理论上,VARCHAR(n) 的最大 n 值是 65535。但是,由于需要考虑存储开销(即变长字段长度列表和 NULL 值列表所占用的字节数),最大 n 值需要减去这些开销。具体地:
    • 如果字段允许为 NULL,NULL 值列表占用 1 字节。
    • 由于 VARCHAR(65535) 的最大存储字节数大于 255 字节,所以变长字段长度列表占用 2 字节。

因此,在这种情况下,VARCHAR(n) 中 n 的最大值为 65532,即 65535 - 2(变长字段长度列表)- 1(NULL 值列表) = 65532。

  • 字符集为 UTF-8: 在 UTF-8 字符集下,一个字符最多需要 3 个字节,因此最大 n 值为 65532/3 = 21844。

多字段的情况

当一个表中有多个字段时,需要确保所有字段的总长度,加上变长字段长度列表和 NULL 值列表所占用的字节数,不超过 65535 字节。因此,VARCHAR(n) 的最大值也会受到其他字段的影响,需要根据具体情况进行计算。



DATETIME和TIMESTAMP区别

相似点

  1. 存储格式

    • DATETIMETIMESTAMP 都用于存储日期和时间,格式为 YYYY-MM-DD HH:MM:SS
    • 两者都支持常见的日期和时间操作,如比较、计算和格式化。
  2. 支持的范围

    • 两者都能够精确到秒级别。

不同点

  1. 存储范围

    • DATETIME:存储的日期和时间范围为 1000-01-01 00:00:009999-12-31 23:59:59,能够表示从公元1000年至9999年的日期和时间。
    • TIMESTAMP:存储的日期和时间范围为 1970-01-01 00:00:01 UTC2038-01-19 03:14:07 UTC。这是因为 TIMESTAMP 使用 Unix 时间戳来存储数据,这个范围限制了 TIMESTAMP 只能表示从1970年到2038年之间的日期和时间。
  2. 存储方式和占用空间

    • DATETIME:存储的是实际的日期和时间值,不受时区影响,占用 8 字节 的存储空间。
    • TIMESTAMP:存储的是 Unix 时间戳(表示从 1970-01-01 00:00:00 UTC 开始的秒数),占用 4 字节 的存储空间。在涉及大量数据时,TIMESTAMP 会更节省存储空间。
  3. 时区支持

    • DATETIME:不受时区影响,存储的值与时区无关。无论在哪个时区查询,存储的值都是相同的。
    • TIMESTAMP:受时区影响,MySQL 会根据服务器的时区设置将存储值自动转换为 UTC 时间保存。当查询时,MySQL 会将其转换回当前会话的时区。因此,在不同的时区设置下,查询 TIMESTAMP 字段可能会得到不同的值。
  4. 自动更新和初始化

    • DATETIME:需要手动设置日期和时间值,默认情况下不会自动更新。
    • TIMESTAMP:支持自动更新和自动初始化。在表定义时,可以设置 TIMESTAMP 字段自动记录插入或更新记录的当前时间,这对于审计或记录变更时间的场景非常有用。


CHAR 和 VARCHAR 区别?如何选择

CHAR 和 VARCHAR 的主要区别在于存储方式、空间利用率和性能:

  • CHAR:1.定长字符串,始终占用固定的空间。2.适合存储固定长度的数据(如国家代码),访问速度较快。3.空间利用率较低,但性能稳定。
  • VARCHAR:1.变长字符串,占用实际数据长度的空间加上 1-2 个字节用于存储长度信息。2.适合存储长度可变的数据(如姓名、地址),节省空间。3.在处理变长数据时,可能稍微影响性能。

选择指南:
● CHAR:用于固定长度字符串,数据长度一致的情况。
● VARCHAR:用于长度可变的字符串,数据长度不固定时更灵活。



货币用什么字段类型

在 MySQL 中记录货币值时,通常推荐使用 DECIMAL 数据类型。这是因为货币通常要求高精度和精确的小数位数,而 DECIMAL 数据类型能够提供这种精确度。

为什么选择 DECIMAL?
● 精确度:DECIMAL 是一种定点数类型,专门设计用于存储需要高精度的小数值(如货币)。与浮点数类型(如 FLOAT 和 DOUBLE)不同,DECIMAL 不会因为二进制浮点数存储格式而引入舍入误差,因此可以准确地表示小数。
● 指定精度和标度:你可以为 DECIMAL 类型指定精度(总位数)和标度(小数点后的位数)。例如,DECIMAL(10, 2) 可以存储最多 10 位数字,其中包括 2 位小数。这使得它非常适合表示货币值。
● 适应货币运算:使用 DECIMAL 可以确保在涉及货币的加、减、乘、除运算中保持精确的结果,这对财务计算非常重要。

示例
● DECIMAL(10, 2) 表示可以存储最多 10 位数字,其中小数点后有 2 位。
● 这意味着最大值为 99,999,999.99,最小值为 -99,999,999.99。

PS:在Java里呢?金额用Long还是Bigdecimal?
首先double和float肯定排除,因为它们底层会采用科学计数法,即转换成二进制进行计算,从而导致小数点无限位的问题进而精度丢失。


Long类型在存储的时候,比如要保留小数点到分,那么存储的时候乘以100,取的时候除以100以达到效果。本质上还是一样,只不过long属于隐式小数点,而Bigdecimal属于显示小数点。


我们之前的项目因为只需要保留到分所以使用Long,但是如果项目对精确位数有要求,还是推荐在代码层面统一的使用Bigdecimal,这样方便我们进行计算,然后存储的时候用long会节省内存一点,但也是视情况而定,如果精确的位数要求特别高,那么long类型每次都要乘以很大的数,存储性能也就荡然无存了。所以如果在需求阶段无法确认小数点后面的位数或者要求小数点后面位数较多那么就用Bigdecimal来表示金额。


BigDecimal 是 Java 中一个用于处理任意精度的浮点数类,定义在 java.math 包中。与基本数据类型(如 float 和 double)相比,BigDecimal 主要用于解决由于浮点数精度问题而引起的计算不准确的问题。它特别适合于金融计算和需要高精确度的场景。
主要特点:
1.任意精度:BigDecimal 可以表示任意大小和精度的数字,允许你进行高精度的计算。
2.避免精度问题:使用 BigDecimal 可以避免浮点数在四舍五入和精度丢失方面常见的问题。
3.不可变性:BigDecimal 对象是不可变的,这意味着一旦创建,值就不能被改变。每次进行运算时,会返回一个新的 BigDecimal 对象。
4.支持四舍五入:提供了多种四舍五入策略,适合不同的应用场景。



概念与对比

MySQL 的基础架构

MySQL 的基础架构可以概括为两层结构:Server 层和存储引擎层,再加上与用户直接交互的客户端层。

1. 客户端层
这是用户与 MySQL 服务器交互的入口。用户通过客户端发送 SQL 语句,MySQL 会对这些请求进行处理。客户端层主要处理连接请求、用户认证和安全性管理等。

2. Server 层
这是 MySQL 的核心部分,负责处理大多数的数据库管理功能和 SQL 语句的执行。Server 层可以细分为以下几个模块:

  • 连接器:负责管理客户端与 MySQL 服务器之间的连接(TCP三次握手),包括验证用户身份、管理权限等。连接可以是短连接(每次查询后断开)或长连接(持续保持)。

是否使用短连接或长连接主要由应用程序的设计需求和数据库访问模式决定。连接池的使用也可以在短连接和长连接之间提供一种平衡,以减少频繁的连接开销并提高数据库访问的效率。

  • 查询缓存(已在 MySQL 8.0 中移除):在处理查询请求前,MySQL 会先检查查询缓存,如果缓存中有对应的结果则直接返回。否则,继续进行查询处理。查询缓存主要用于保存已经执行过的查询结果,以提升查询效率。

  • 解析器:对收到的 SQL 语句进行解析,完成词法分析和语法分析,并生成对应的语法树。如果 SQL 语句语法有误,会在这个阶段报错。

  • 预处理器:对解析后的语句进行预处理,例如检查表和字段是否存在,展开 select * 为实际列名等。

  • 优化器:在 SQL 执行前,优化器会根据查询语句选择最佳的执行计划。比如在多索引情况下,优化器会选择最优的索引来执行查询。

  • 执行器:执行器按照优化器选择的执行计划,实际执行查询语句,并与存储引擎交互获取数据。执行器会逐条从存储引擎中获取记录并判断是否符合查询条件,然后将符合条件的数据返回给客户端。

3. 存储引擎层

存储引擎层负责 MySQL 数据的实际存储与提取,不同的存储引擎提供不同的数据管理功能。常见的存储引擎有 InnoDB、MyISAM 等。InnoDB 是目前最常用的存储引擎,默认支持事务,并通过 B+ 树来管理索引和数据存储。存储引擎层与 Server 层通过 API 通信,Server 层并不直接了解具体的存储引擎如何实现,只需通过接口获取或存储数据即可。



PostgreSQL和MySQL对比

PostgreSQL(简称PGSQL)和MySQL需要根据具体业务需求来选择使用哪一个,下面是它俩之间的一些区别:

  • 特性上,PGSQL提供了一些高级特性,比如物化视图,公共表表达式和窗口函数(mysql8.0也引入了)等等,而MySQL在一些Web开发中表现更加优秀
  • 性能上,总体MySQL的性能更加突出特别是在读密集的场景中,而PGSQL在处理复杂查询和写密集操作时候更有优势
  • —致性和数据完整性,PGSQL严格遵循SQL标准提供了全面的ACID支持,而MySQL呢虽然也支持ACID,但支持程度会受存到存储引擎的影响, MySQL 原生的 MyISAM 引擎就不支持事务
  • 扩展性方面,PGSQL支持多种自定义扩展,比如说自定义数据类型、操作符等等,而MySQL则是在分区方面表现更好

从两种数据库的选择方面,有几个方面的考虑因素:

  • 从应用范围来说,PGSQL更适合具有频繁写入操作和复杂查询的企业级应用程序,MySQL适合创建用户较少的内部应用程序,或者创建具有更多读取次数和较少数据更新的信息存储引擎
  • 从性能上说,如果应用程序需要频繁更新数据,则适合PGSQL,如果要频繁读取数据,则适合MySQL
  • 在数据写入层面,MySQL使用写锁定来实现真正的并发性,而PGSQL内置了多版本并发控制支持,没有读写锁定,如果要进行频繁并发的写入操作,PGSQL数据库的表现会更加优异
  • 在数据读取层面,PGSOL会创建一个新的系统进程,为每个连接到数据库的用户分配大量内存,而MySQL是为多个用户创建一个单一进程,因此对于主要向用户读取和显示数据的应用程序,MySQL要比PGSOL更好
  • 学习起来的话MySQL更好上手,而PGSQL需要复杂的基础设置和问题排查经验




InnoDB

MyISAM和innoDB引擎的区别

主要区别有:

  • 索引结构不同。MyISAM存储引擎使用的是B树,叶子节点和非叶子节点都可以存储实际数据。而innoDB是B+树。
  • 对于事务的支持不同。MyISAM不支持事务,而innoDB支持ACID特性和一个事务处理。
  • 对于锁的支持不同,MyISAM只支持表锁,而InnoDB可以根据不同的情况去支持行锁、表锁、间隙锁、临键锁等。
  • MyISAM不支持外键,lnnoDB支持外键(数据库引擎能够在表与表之间建立并强制执行外键约束)
  • count 的效率:InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快。

你可能会好奇,为什么 count 函数需要通过遍历的方式来统计记录个数?
使用 MyISAM 引擎时,执行 count 函数只需要 O(1 )复杂度,这是因为每张 MyISAM 的数据表都有一个 meta 信息有存储了row_count值,由表级锁保证一致性,所以直接读取 row_count 值就是 count 函数的执行结果。
而 InnoDB 存储引擎是支持事务的,同一个时刻的多个查询,由于多版本并发控制(MVCC)的原因,InnoDB 表“应该返回多少行”也是不确定的,所以无法像 MyISAM一样,只维护一个 row_count 变量。所以,在使用 InnoDB 存储引擎时,就需要扫描表来统计具体的记录。

根据这些特性,在实际应用中可以根据不同的场景去选择合适的存储引擎,比如要支持事务那必须选择InnoDB,如果大部分的表操作都是查询则可以选择MyISAM。



为什么InnoDB是默认引擎

InnoDB之所以被MySQL选为默认存储引擎,主要是因为它在事务支持、并发性能和崩溃恢复方面的显著优势。

  • 事务支持:InnoDB 引擎完全支持 ACID(原子性、一致性、隔离性、持久性)属性,能够确保数据库操作的完整性和可靠性。相比之下,MyISAM 存储引擎并不支持事务,这使得 InnoDB 在处理需要事务控制的复杂操作时具有明显的优势。

  • 并发性能:InnoDB 采用行级锁定机制,这种细粒度的锁定方式允许多个用户同时对不同的行进行操作,从而显著提升并发性能。相对而言,MyISAM 只支持表级锁定,锁的粒度较大,当多个用户试图同时访问相同的表时,可能会导致性能瓶颈。

  • 崩溃恢复:InnoDB 通过使用 redo 日志实现了崩溃恢复功能。这意味着当数据库遇到异常情况(例如断电)时,InnoDB 可以通过日志文件恢复到最近一次的稳定状态,从而确保数据的持久性和一致性。而 MyISAM 不具备这种崩溃恢复功能,在异常情况下可能会导致数据丢失或损坏。



InnoDB如何存储数据?插入到页的过程

InnoDB 的数据是按「数据页」为单位来读写的,默认数据页大小为 16 KB。每个数据页之间通过双向链表的形式组织起来,物理上不连续,但是逻辑上连续。

什么是InnoDB的页、区、段?
● 页(Page):InnoDB 存储数据的基本单位,通常大小为 16KB。所有数据(包括行数据、索引、系统信息等)都存储在页中。● 区(Extent):由 64 个连续的页组成的单元,大小为 1MB。用于管理和分配大块的磁盘空间,减少碎片。● 段(Segment):由一个或多个区组成的逻辑存储结构,管理表的数据段、索引段和回滚段,便于动态扩展存储空间。

页并不是所有的空间都是用来存放数据的,会有一些固定的信息,如,页头,页尾,页码,校验码等等。

数据页内包含用户记录,每个记录之间用单向链表的方式组织起来,为了加快在数据页内高效查询记录,设计了一个页目录,页目录存储各个槽(分组),且主键值是有序的,于是可以通过二分查找法的方式进行检索从而提高效率。

为了高效查询记录所在的数据页,InnoDB 采用 b+ 树作为索引,每个节点都是一个数据页。

如果叶子节点存储的是实际数据的就是聚簇索引,一个表只能有一个聚簇索引;如果叶子节点存储的不是实际数据,而是主键值则就是二级索引,一个表中可以有多个二级索引。

InnoDB插入记录到页的过程?
InnoDB 插入记录到页的过程涉及以下步骤:1.查找合适的页:通过 B+ 树定位目标页。2.页分裂(如果必要):当页空间不足时,执行页分裂。3.找到插入点:在页中查找合适的插入位置。4.插入记录:将记录插入到页中,并更新页目录。5.更新元数据:更新页头信息,并将页标记为脏页。6.更新索引:如果涉及二级索引,更新相应的索引页。7.日志记录:生成 Redo Log 和 Undo Log 以支持崩溃恢复和事务回滚。8.提交事务:在事务提交时持久化更改。



InnoDB为何推荐用自增主键

InnoDB 推荐使用自增主键作为聚簇索引的主键,是因为自增主键可以:

  • 减少数据页分裂

    • 自增主键:插入操作是顺序进行的,新的记录始终附加在最后,减少了数据
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值