Mysql:索引与B+树

在日常MySQL建表中,我们有三种定义主键的方式。不同的主键定义方式,在InnoDB底层B+树聚簇索引的创建时机、磁盘开销、底层逻辑完全不同。

方式一:字段后直接定义主键(内联主键)

sql 复制代码
CREATE TABLE user(
    id INT PRIMARY KEY,
    name VARCHAR(20)
);
 
  1. 建表语句执行的同时,InnoDB直接以当前主键字段构建聚簇索引B+树 。

  2. 数据在磁盘物理页中有序连续存储 。

  3. 后续新增数据直接按照B+树规则插入,不会产生任何表重构。

  4. 性能最优,是开发中最推荐的方式。

总结

建表 + 聚簇B+树 一次性生成,零额外开销。

方式二:先建表,后续再追加主键

sql 复制代码
CREATE TABLE user(
    id INT,
    name VARCHAR(20)
);


ALTER TABLE user ADD PRIMARY KEY(id);
  1. InnoDB表必须要有聚簇索引。建表无显式主键时,InnoDB按照优先级自动生成临时的聚簇B+树。

无主键时优先级:
自定义主键 > 唯一索引 > 隐藏6字节 row_id

  1. 执行 alter 新增主键时:

销毁原本的临时B+树,全表数据重新磁盘排序, 基于新的自定义主键,重新完整构建一颗全新的聚簇B+树

  1. 整个过程会产生大量IO开销,表数据量越大,性能损耗越严重。

4**.删除主键也会触发全表重构。**

总结

数据量大时会产生大量磁盘IO、锁表、性能雪崩,生产环境严禁后期添加主键。

方式三:定义主键 + 额外普通索引/联合索引

sql 复制代码
CREATE TABLE user(
    id INT PRIMARY KEY,
    name VARCHAR(20),
    INDEX idx_name(name)
);

InnoDB会同时存在两颗及以上B+树:

  1. 聚簇索引B+树

叶子节点存储完整的整行数据,以主键为排序规则 。

  1. 二级索引(普通索引)B+树

叶子节点只存储索引列的值 + 对应的主键值 ,不存储整行数据。

  1. 回表机制

当通过二级索引查询数据时:
先在二级B+树找到对应主键 → 再拿着主键去聚簇B+树中查询完整数据,这个过程叫做回表查询。

复合索引可以不回表,已知 a 找 b ,在(a,b)二级B+树能直接找到 b

索引创建原则

  1. 比较频繁作为查询条件的字段应该创建索引

  2. 唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件

3.更新非常频繁的字段不适合作创建索引

  1. 不会出现在where子句中的字段不该创建索引
相关推荐
川石课堂软件测试7 小时前
学习软件测试需掌握的一些知识
数据库·python·sql·功能测试·网络协议·mysql·http
1024奇点14 小时前
【仓颉语言入门 · 第二篇 第 12 课】
开发语言·数据库·ide·mysql·开源
冰暮流星14 小时前
mysql之insert优化
数据库·mysql
北方的银狐-Zero14 小时前
OntoL 7.0|面向工业多智能体的语义本体套件,让异构系统真正 “看懂彼此”——OntoL的本体产品矩阵
人工智能·mysql·sqlite·1024程序员节·本体论·本体产品
瑞克-桑切斯16 小时前
4、MySQL 索引与事务
数据库·mysql
二宝哥16 小时前
【问题】本地启动springboot项目启动flowable引擎会提示数据库脚本错误,同事本地启动没有报错(MySQL表明大小写敏感参数)
数据库·mysql
瑞克-桑切斯17 小时前
2、 MySQL 主从复制与读写分离
数据库·mysql
秋饼18 小时前
MySQL 分库分表完全指南:ShardingSphere-JDBC 实战、分片键选型、场景边界、20 个生产坑与 30 道面试点
java·mysql·面试·shardingsphere·分库分表·后端架构
JavaPub-rodert18 小时前
王仕宇分享:把 MySQL 排障做成 AI Agent,慢 SQL、锁等待、连接数和主从异常都能自动查
人工智能·sql·mysql