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子句中的字段不该创建索引
相关推荐
王琦03181 分钟前
生产环境中使用通用二进制包安装
mysql
蓝田~3 小时前
MySQL慢查询怎么优化?B+Tree索引原理+MVCC读不阻塞写+EXPLAIN执行计划,从5秒到0.05秒
数据库·mysql
Herbert_hwt3 小时前
MySQL学习前言:关于MySQL的历史与当下学习的必要性
mysql
时间的拾荒人4 小时前
MySQL 视图详解
android·数据库·mysql
尽兴-5 小时前
企业数据库选型与演进:Oracle、达梦、MySQL 与分库分表实践
数据库·mysql·oracle·分库分表
IT瑞先生6 小时前
Docker快速部署Mysql的三种方法——实操篇
mysql·adb·docker
数据库小学妹6 小时前
MySQL在线DDL实战:ALGORITHM三种算法对比+gh-ost变更管理SOP
mysql·dba·数据库运维·在线ddl·mdl锁·sql变更管理
Ethan01077 小时前
隔离级别管读,乐观锁管写——RC/RR 与写冲突的本质
mysql
熊文豪8 小时前
【金仓数据库征文】不装中间件的 MySQL→金仓在线迁移,mysql_fdw 全流程,和一个差点漏掉的 emoji
数据库·mysql·中间件·电科金仓
C++、Java和Python的菜鸟8 小时前
第5章 后端Web基础 (MySQL基础)
前端·mysql·adb