MySQL底层原理(第二期)

112 阅读6分钟

十、索引组织表:万物皆索引(写多读少用堆表,读多写少用索引组织表)

(堆表和索引组织表有什么区别?分别应用场景是什么?)

堆表中的数据无序存放, 数据的排序完全依赖于索引。而索引组织表,数据根据主键排序存放在索引中,主键索引也叫聚集索引(Clustered Index)。在索引组织表中,数据即索引,索引即数据。

InnoDB 存储引擎的数据是根据主键索引排序存储的,除了主键索引外,其他的索引都称之为二级索引(Secondeary Index), 或非聚集索引(None Clustered Index)。

二级索引也是一颗 B+ 树索引,但它和主键索引不同的是叶子节点存放的是主键值。

“二级索引通过主键索引进行再一次查询”的操作叫作“回表”

存储结构

堆表:数据行按照插入顺序随机存储,没有特定的物理排序。通过额外的索引(如B+树)来加速查询,索引中存储指向实际数据的指针(如ROWID)。 索引组织表:数据行按照主键(或指定索引键)的值排序存储,表本身就是一个B+树索引结构,数据与索引合并存储,无需额外的索引。

查询性能

堆表: 优点:插入速度快(无需维护排序),适合频繁写入的场景。 缺点:范围查询或主键查询需通过索引二次访问数据块,可能增加I/O开销。 索引组织表: 优点:主键查询效率高(直接定位数据),范围查询性能优(数据物理有序)。 缺点:插入和更新可能较慢(需维护B+树结构)。

空间占用

堆表:需额外空间存储索引,但初始插入时空间利用率较高。 索引组织表:无重复存储(索引即数据),但可能因溢出存储(如Oracle的OVERFLOW段)增加复杂度。

适用场景

堆表适合: 频繁插入、删除或更新的OLTP场景(如日志表)。 无主键或主键查询不频繁的表。 索引组织表适合: 主键查询频繁或需要范围查询的表(如订单表、代码字典表)。 数据需物理有序存储的场景(如时间序列数据)。

十一、组合索引:用好,性能提升 10 倍!

(联合索引的结构是怎样的?如何利用联合索引提升查询性能?)

联合索引的结构

联合索引(Composite Index)是基于多个列组合创建的B+树结构索引,其核心特点如下:

存储方式:数据按照索引定义的列顺序排序(如 (a, b, c) 先按 a 排序,a 相同再按 b 排序,以此类推)37。 B+树实现:每个节点存储多列键值组合,叶子节点按顺序链接,支持高效的范围查询和排序37。 最左前缀原则:查询必须从索引的最左列开始匹配,否则索引可能失效(如索引 (a, b, c) 需包含 a 才能生效)256

如何利用联合索引提升查询性能

遵循最左前缀原则:

完全匹配:查询条件包含索引所有列且顺序一致时,性能最优。

部分匹配:仅使用索引左侧列仍可生效。

失效场景:跳过左侧列会导致索引失效。

覆盖索引优化:若查询字段均包含在联合索引中,可避免回表(直接从索引获取数据)

排序与分组优化:联合索引可加速 ORDER BY 或 GROUP BY 操作

范围查询的注意事项:范围查询(如 >、<)会中断后续列的索引使用

十二、索引失效有哪些?

(有哪些索引失效的场景?为什么会失效?)

当我们使用左或者左右模糊匹配的时候,也就是 like %xx 或者 like %xx%这两种方式都会造成索引失效;

当我们在查询条件中对索引列使用函数,就会导致索引失效。

当我们在查询条件中对索引列进行表达式计算,也是无法走索引的。

MySQL 在遇到字符串和数字比较的时候,会自动把字符串转为数字,然后再进行比较。如果字符串是索引列,而条件语句中的输入参数是数字的话,那么索引列会发生隐式类型转换,由于隐式类型转换是通过 CAST 函数实现的,等同于对索引列使用了函数,所以就会导致索引失效。

联合索引要能正确使用需要遵循最左匹配原则,也就是按照最左优先的方式进行索引的匹配,否则就会导致索引失效。

在 WHERE 子句中,如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列,那么索引会失效。

十三、索引出错:请理解 CBO 的工作原理

(MySQL 数据库中的优化器是怎么执行的?根据什么标准选择索引的?)

优化器执行流程

SQL 解析与语法树生成:优化器首先解析 SQL 语句,生成语法树(Parse Tree),检查语法合法性

查询重写与逻辑优化:消除冗余条件(如 WHERE 1=1)、外连接转内连接、子查询优化(如 EXISTS 转 IN)、常量表达式预计算(如 WHERE a=5 AND b>a 简化为 WHERE a=5 AND b>5)

统计信息收集:基于表的行数、索引基数(Cardinality)、数据分布等统计信息估算成本

生成候选执行计划:评估不同索引、连接顺序(如多表 JOIN 时动态规划或贪心算法选择顺序)、覆盖索引、索引下推(Index Condition Pushdown)等优化策略

成本估算与计划选择:计算每个计划的 I/O(磁盘读取)、CPU(比较/排序)、内存开销。选择总成本最低的计划(通过 SHOW STATUS LIKE 'Last_query_cost' 查看)

执行计划生成与传递:最终计划以树形结构传递给执行引擎(如全表扫描、索引扫描、临时表排序等)

索引选择标准

索引选择性:高选择性(唯一值多)的列优先使用索引(如主键)、低选择性(重复值多)的列可能触发全表扫描

查询条件匹配度:遵循最左前缀原则(联合索引需从左到右匹配)、范围查询(如 WHERE a>10)可能中断后续索引列的使用

覆盖索引:若索引包含查询所有字段(如 SELECT id FROM t WHERE id=1),避免回表

排序与分组优化:ORDER BY/GROUP BY 字段与索引顺序一致时,避免额外排序511

统计信息准确性:InnoDB 的统计信息可能不实时(需 ANALYZE TABLE 更新)、表数据量变化大时,优化器可能误判

启发式规则:避免全表扫描(优先尝试索引)、小表直接全扫描(成本低于索引)