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子句中的字段不该创建索引
相关推荐
Database_Cool_13 小时前
AnalyticDB MySQL vs StarRocks/ByteHouse:云数仓选型指南——全托管 vs 自建方案
数据库·数据仓库·mysql·阿里云
AI人工智能+电脑小能手14 小时前
【大白话说Java面试题 第99题】【Mysql篇】第29题:如何选择合适的分布式主键方案?
java·数据库·分布式·mysql·面试
拾贰_C16 小时前
【mysql | windows | installation】 MySQL5.安装
数据库·windows·mysql
yuezhilangniao17 小时前
MySQL 8.0.32 二进制安装脚本 和初始化 操作系统版本rocky86
数据库·mysql·adb
学代码的真由酱18 小时前
MySQL数据库进阶-数据库设计实践-Java
数据库·mysql·数据库设计
遇事不決洛必達18 小时前
【数据库系列】本地映射云服务器Mysql的方法
服务器·数据库·mysql·定时任务
yuezhilangniao19 小时前
xtr备份prepare到底变化了啥
mysql
yyk的萌19 小时前
创建属于自己的mysql的mcp
mysql·adb·ai·mcp
流烟默19 小时前
腾讯云Centos7.6使用yum安装MySQL8
mysql·centos·腾讯云
仙俊红19 小时前
如何优化 MySQL 深分页 SQL
android·sql·mysql