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子句中的字段不该创建索引
相关推荐
螺蛳粉 螺蛳粉6 小时前
MySQL 分布式集群系列 · 第五篇——全方位对比:NDB、MGR、主从复制、分库分表怎么选?
数据库·分布式·mysql
泡泡鱼(敲代码中)7 小时前
MySQL 学习笔记:DCL、函数与约束 —— 安全、效率、完整性的三板斧
开发语言·笔记·sql·学习·mysql·gitee
这个DBA有点耶10 小时前
从OLTP到OLAP到HTAP:数据库负载分类的技术演进与选型指南
数据库·mysql·架构
何以解忧,唯有..12 小时前
MySQL 是如何实现事务隔离的?
mysql
螺蛳粉 螺蛳粉12 小时前
mysql备份脚本
mysql
IT大白鼠12 小时前
MySQL 高可用系列 · Orchestrator + ProxySQL 第三篇——核心原理精讲
数据库·mysql·架构
国际云,接待14 小时前
云服务器跨厂商迁移怎么尽量不停机:用 rsync、MySQL binlog 和 DNS TTL 做双阶段切换
运维·服务器·mysql
小白学大数据15 小时前
Python 项目实战:用 Flask 构建生产级 MySQL 增删改查 REST API
开发语言·人工智能·python·mysql·flask
minebmw715 小时前
第 02 讲 基础架构:一条 SQL 查询语句是如何执行的?
mysql
jaysee-sjc15 小时前
【苍穹外卖】Day01:从零认识企业级项目开发
java·开发语言·数据库·mysql·spring·intellij-idea·mybatis