当前位置: 首页 > article >正文

1-002:MySQL InnoDB引擎中的聚簇索引和非聚簇索引有什么区别?

MySQL InnoDB 存储引擎 中,索引主要分为 聚簇索引(Clustered Index)非聚簇索引(Secondary Index)。它们的主要区别如下:


1. 聚簇索引(Clustered Index)

定义

  • 聚簇索引是表数据存储的方式,即 索引和数据在一起叶子节点存储的是完整的行记录
  • InnoDB 中的主键索引就是聚簇索引(如果没有主键,InnoDB 会选择一个 UNIQUE 索引作为聚簇索引;如果没有 UNIQUE,InnoDB 会自动生成一个隐藏的 rowid)。

存储结构

  • 使用 B+ 树 结构存储,叶子节点存放 完整的行数据
  • 数据物理存储顺序和主键索引顺序一致。

特点

  • 访问主键索引时,直接获取整行数据,查询速度快。
  • 数据存储在主键索引的叶子节点上表本身就是一棵 B+ 树
  • 适用于 基于主键的查询、范围查询
  • 更新、删除、插入操作可能导致数据的页分裂,影响性能。

示例

CREATE TABLE users (
    id INT PRIMARY KEY,  -- 主键,自动成为聚簇索引
    name VARCHAR(50),
    age INT
);

users 表中,id 作为 聚簇索引,数据在磁盘上的存储顺序与 id 值的顺序相同。


2. 非聚簇索引(Secondary Index / 辅助索引)

定义

  • 非聚簇索引是独立于数据存储的索引叶子节点存储的是主键值,而不是完整的行数据。
  • 访问非聚簇索引时,需要先查找索引,再通过主键回表查询数据,这种过程称为 回表查询(回溯查询,Bookmark Lookup)

存储结构

  • 也是 B+ 树 结构,但叶子节点存储的是主键值,而非完整的行记录。

特点

  • 加速非主键列的查询(适用于 WHERE 条件非主键字段)。
  • 需要二次查询(先通过非聚簇索引找到主键值,再回表查询完整数据)。
  • 索引占用空间较大,需要额外存储主键值。

示例

CREATE TABLE users (
    id INT PRIMARY KEY,  -- 主键(聚簇索引)
    name VARCHAR(50),
    age INT,
    INDEX idx_name (name)  -- 非聚簇索引
);

如果执行:

SELECT * FROM users WHERE name = 'Alice';

查询过程如下:

  1. 先在 非聚簇索引 idx_name 中查找 Alice,获取其 主键 id
  2. 使用 id聚簇索引 中回表查找完整的行数据。

3. 聚簇索引 vs. 非聚簇索引

对比项聚簇索引(Clustered Index)非聚簇索引(Secondary Index)
存储结构叶子节点存储 完整行数据叶子节点存储 主键值
查询速度主键查询快(无需回表)非主键查询慢(需要回表)
插入速度(影响数据存储顺序)较快(不影响主键顺序)
更新操作影响数据物理存储顺序,可能导致页分裂更新可能导致回表查询增加
占用空间只存储数据本身需要存储 索引列 + 主键值,占用空间大
适用场景主键查询,范围查询查询非主键列,提高查询性能

4. 什么时候使用聚簇索引 vs. 非聚簇索引?

适合使用聚簇索引的场景

  • 主键查询多,如 WHERE id = 100;
  • 范围查询多,如 BETWEEN 100 AND 200;
  • 数据表的主键是有序递增的(如 AUTO_INCREMENT),避免页分裂。

适合使用非聚簇索引的场景

  • 查询非主键字段时,如 WHERE name = 'Alice';
  • 涉及联合查询,如 INDEX (name, age);
  • 表很大,不希望频繁回表查询(可以使用 覆盖索引,避免回表)。

5. 可能的优化方案

  1. 覆盖索引(Covering Index)

    • 避免回表,提高查询性能

    • 优化方法:如果查询的数据只包含索引字段,则直接从索引中获取数据,不需要回表。

    • 示例:

      CREATE INDEX idx_name_age ON users(name, age);
      SELECT name, age FROM users WHERE name = 'Alice';  -- 只查 name 和 age,不回表
      
  2. 使用合适的主键

    • 采用 自增主键,避免页分裂,提高插入性能。
    • 避免使用 UUID、随机值作为主键,会导致索引失效、性能下降。
  3. 减少回表查询

    • 索引覆盖查询,如 SELECT name FROM users WHERE name = 'Alice';
    • 适当调整索引列,如 INDEX (name, age) 避免多次回表。

总结

  • InnoDB 中的主键索引是聚簇索引,数据存储在 B+ 树的叶子节点上,查询主键时速度最快
  • 非聚簇索引存储的是主键值,查询时需要回表查询完整数据,适用于非主键查询场景。
  • 优化索引可以减少回表查询,提高 MySQL 查询性能

http://www.kler.cn/a/579616.html

相关文章:

  • 逐梦DBA:Linux下MySQL字符集的处理
  • OkHttp 之任务调度模块源码分析
  • 为php添加额外的功能模块
  • 论文阅读笔记——OpenVLA: An Open-Source Vision-Language-Action Model
  • YC 孵化项目 Pinch:实时语音翻译视频会议平台;Mistral OCR:能处理多语言多模态复杂文档丨日报
  • 数据量过大的时候导出数据很慢
  • 链式多分支规则树模型结构
  • robotjs获取鼠标位置
  • c++介绍锁四
  • 快速排序(二叉树的前序递归遍历思想)
  • 【three.js】动画系统完全指南 - 从事件循环到工业级动画架构
  • MobileBERT: 一种适用于资源有限设备的紧凑型任务无关BERT
  • 关于C/C++语言的初学者在哪刷题,怎么刷题
  • 软件系统压力测试方案,压力测试报告模版(Word原件)
  • OSPF-单区域的配置
  • 反射是什么?
  • 数学建模-1:对变化建模
  • Python正则表达式完全指南:从入门到精通
  • 【Linux网络(一)】初始网络
  • Linux:多线程(单例模式,其他常见的锁,读者写者问题)