一、存储引擎
MySQL 的体系结构是一个典型的三层架构,由 连接层(Connect/Client Layer) 、服务层(Server Layer) 、存储引擎层(Storage Engine Layer) 组成。每一层各司其职,协同完成 SQL 语句的接收、解析、执行和数据存储。

(一)MySQL 体系结构
1. 连接层 / 客户端接口层(Connection / Client Layer)
连接层是 MySQL 与客户端交互的入口,负责管理连接、验证用户身份以及处理网络通信。
主要功能:
连接管理:接受客户端连接请求,为每个客户端分配独立的连接线程。
安全认证:验证用户名、密码及权限,确保数据安全。
网络通信:通过 TCP/IP 或 Unix Socket 与客户端交互。
组成部分:
MySQL 客户端(如 mysql 命令行工具、JDBC/ODBC 驱动程序)
连接线程(每个客户端连接对应一个线程)
协议解析器(如 MySQL 客户端协议,用于解析请求和响应)
2. 服务层 / 服务器层(Server Layer)
服务层是 MySQL 的核心层,负责 SQL 解析、优化、执行以及缓存和事务管理。
主要功能:
| 功能模块 | 描述 |
|---|---|
| SQL 解析器(Parser) | 将 SQL 语句解析成抽象语法树(AST) |
| 优化器(Optimizer) | 生成最优执行计划,包括索引选择、表连接顺序、查询重写(如子查询优化) |
| 查询缓存(Query Cache) | 缓存查询结果以提高查询速度(MySQL 8.0 已废弃) |
| 事务管理(Transaction Manager) | 管理事务提交(COMMIT)与回滚(ROLLBACK),保证 ACID 特性 |
| 权限检查(Privilege Manager) | 控制数据库对象访问权限,保证安全性 |
SQL 执行流程:
SQL -> Parser(解析) -> Optimizer(优化) -> Executor(执行器) -> Storage Engine(存储引擎)
3. 存储引擎层(Storage Engine Layer)
存储引擎是 MySQL 底层实际存储数据和索引的模块,负责数据的持久化、索引管理以及事务和日志处理。
主要功能:
数据存储与检索:负责表数据文件和索引文件的管理。
事务支持:InnoDB 支持事务、行级锁和崩溃恢复。
索引管理:管理 B+ 树索引、全文索引等。
日志管理:
Redo Log:重做日志,用于崩溃恢复。
Undo Log:回滚日志,用于事务回滚。
常用存储引擎:
| 引擎 | 特点 |
|---|---|
| InnoDB | 支持事务、外键、行级锁,适合高并发业务 |
| MyISAM | 不支持事务,适合读多写少的场景 |
| Memory | 数据存储在内存中,访问速度快,适合临时表和缓存 |
| CSV / Archive / NDBCluster | 特殊用途,如日志存储或集群应用 |
(二)存储引擎简介
存储引擎是 MySQL 实现数据存储、索引、查询和更新的技术方案。每个表可选择不同的存储引擎,创建表时可指定引擎类型:
sql
CREATE TABLE 表名 (
字段1 类型 [COMMENT '字段1注释'],
...
字段n 类型 [COMMENT '字段n注释']
) ENGINE=InnoDB [COMMENT='表注释'];
查看 MySQL 支持的存储引擎:
sql
SHOW ENGINES;

(三)存储引擎特点对比
MySQL 支持多种存储引擎,不同引擎适用不同场景。在选择引擎时,需要从事务支持、锁机制、持久化能力及性能特点等方面进行全面比较。
1. InnoDB
介绍
InnoDB 是 MySQL 5.5 之后的默认存储引擎,支持事务、行级锁和崩溃恢复机制,是以 OLTP(高并发事务)为核心设计的通用存储引擎。
特点
支持 ACID 事务模型
行级锁并支持 MVCC,提高并发性能
支持外键(FOREIGN KEY)
基于 Buffer Pool 提供强大的缓存能力
支持崩溃恢复(Redo/Undo 日志)
文件结构
xxx.ibd:独立表空间文件,包含
表数据
聚簇索引
二级索引
元数据(.frm/.sdi)
是否存储在 ibd 取决于参数:innodb_file_per_table
为什么是否生成 .ibd 取决于 innodb_file_per_table?因为该参数决定 InnoDB 是否为每个表分配 独立表空间。
OFF: 所有表都存入 ibdata1,不产生 ibd
ON: 每表一个 ibd
2. MyISAM
介绍
MySQL 早期的默认存储引擎,结构简单、查询速度快,但不支持事务和崩溃恢复。
特点
不支持事务
不支持外键
表级锁(读写互斥)
查询性能高,写性能一般
不支持崩溃恢复
文件结构
xxx.sdi:表结构
xxx.MYD:存储数据
xxx.MYI:存储索引
3. Memory
介绍
Memory(HEAP)引擎使用内存存储数据,因此速度极快,但重启或崩溃后数据会丢失。
特点
所有数据保存在内存中
默认使用 Hash 索引(可选 B+Tree)
表级锁
访问速度最快,适用于临时数据或缓存
文件结构
xxx.sdi:存储表结构
数据不落盘(只存在内存中)
存储引擎对比表
| 特性 | InnoDB | MyISAM | Memory |
|---|---|---|---|
| 事务支持 | ✔ ACID | ✘ | ✘ |
| 锁机制 | 行级锁(高并发) | 表级锁 | 表级锁 |
| 外键支持 | ✔ | ✘ | ✘ |
| 存储方式 | 磁盘 + Buffer Pool | 磁盘(MYD/MYI) | 内存 |
| 索引类型 | B+Tree(聚簇索引) | B+Tree | Hash(默认) |
| 崩溃恢复 | ✔(redo + undo) | ✘ | ✘ |
| 性能特点 | 读写均衡,支持高并发 | 读快写慢 | 极快但不持久 |
| 适用场景 | OLTP、高并发系统 | 查询多写少 | 临时表、缓存 |
(四)存储引擎选择
不同业务类型适合不同的存储引擎,以下是选择建议。
1. InnoDB(默认推荐)
适用于:
高并发读写
需要事务保证的数据(ACID)
需要外键约束保证数据一致性
CRUD 操作频繁的业务系统(如银行、订单、电商)
总结:
大多数业务场景中首选的存储引擎
2. MyISAM
适用于:
读操作远多于写操作
对事务要求不高
对崩溃恢复要求不高
静态或归档数据,例如:日志、配置表
总结:
读多写少,对事务性要求不高的场景
3. Memory
适用于:
需要极高访问速度的缓存场景
需要临时计算的表(如 JOIN 缓存)
小规模、高速、不持久的数据
限制:
数据存内存,重启丢失
表过大可能导致内存耗尽
总结:
临时表、会话缓存、超高速查询
为什么 MySQL 要单独设计"存储引擎层"?
MySQL 的最大特点之一,就是采用可插拔的存储引擎架构(Pluggable Storage Engine Architecture)。这意味着 MySQL 的 SQL 层和底层存储层是完全解耦的:
上层负责 解析 SQL、优化、生成执行计划
下层的存储引擎负责 实际的数据存储、索引、锁、事务机制
(1)存储引擎层的可插拔设计
在 MySQL 中,存储引擎是一种模块化组件,允许系统针对不同业务场景选择最适合的存储方式。
主要体现为:
| 设计能力 | 描述 |
|---|---|
| 每张表可以选择不同存储引擎 | 同一数据库中,表 A 可以是 InnoDB,表 B 可以是 MyISAM |
| 引擎可扩展 | MySQL 可以加载第三方存储引擎,如 TokuDB、RocksDB |
| SQL 层与引擎层解耦 | 执行一条 SQL 时,语法解析、执行计划不受引擎限制 |
| 不同引擎提供不同能力 | 如是否支持事务、外键、锁粒度、索引类型等 |
(2) SQL 层与存储引擎层的协作方式
执行 SQL 时,流程如下:
sql
Server 层(解析/优化/执行计划)
↓
调用存储引擎接口(Handler API)
↓
存储引擎执行实际读写(如 InnoDB)
Server 层依赖存储引擎提供的通用接口(Handler API),这使得:
不同引擎只要实现这些接口,就能接入 MySQL
同样的 SQL 不需要修改即可在不同引擎上执行
这也是 MySQL 与 Oracle、PostgreSQL 等数据库最大的结构差异。
为什么存储引擎层要独立?
因为不同业务,对底层存储的需求差别巨大:
| 场景 | 适合的引擎 | 原因 |
|---|---|---|
| 高并发 OLTP | InnoDB | 事务、行锁、恢复能力强 |
| 读多写少 | MyISAM | 查询快 |
| 极高速访问 | Memory | 全内存存储 |
| 分布式集群 | NDBCluster | 分布式特性 |
传统数据库往往使用一种统一存储方式,但 MySQL 让你可以:
在一套 SQL 上层之下,按需为每张表选择不同的底层存储技术。
这是 MySQL 的独特竞争力。
二、索引(Index)
(一)索引概述
1. 索引是什么?
索引(Index)是一种能够帮助 MySQL 快速定位数据的数据结构。它类似于书籍的目录,通过有序的数据结构加速数据查找,而不需要从表头开始逐行扫描。
在表数据之外,数据库会维护一套额外的数据结构(如 B+Tree、Hash),这些结构以某种方式指向表中的实际数据,从而支持高效的查找算法。
索引 = 有序 + 高效查找 + 附加存储结构。
2. 索引的优点
极大提高查询速度(最核心的作用)
减少服务器 IO
加速排序和分组(ORDER BY、GROUP BY)
提升 JOIN 性能
3. 索引的缺点
占用额外存储空间
影响写性能:INSERT、UPDATE、DELETE 需维护索引结构
少量不当索引可能降低整体性能
索引不是越多越好,需要合理设计。
(二)索引结构
MySQL 的索引由不同存储引擎在底层实现。虽然语法层面统一(如 CREATE INDEX ...),但不同存储引擎支持的索引类型、底层结构及工作机制并不相同。
1. B+Tree 索引(最常用,也是默认索引)
B+Tree(多路平衡树)是 MySQL 最核心、最通用的索引结构,适用于:
等值查询:WHERE id = 10
范围查询:BETWEEN、>、<
排序:ORDER BY
分组:GROUP BY
B+Tree 索引特点
索引节点按顺序排列,适合范围扫描。
搜索效率稳定:树高一般 2~4 层 即可支持千万级数据。
非叶子节点只存索引,不存数据 → 扇出大,树高度更低。
叶子节点通过链表连接 → 顺序扫描性能极高。
不同存储引擎的 B+Tree 差异
InnoDB:聚簇索引(Clustered Index)
主键索引的叶子节点存储整行数据。
非主键索引的叶子节点存储的是主键值(指向主键的二次查找)。
MyISAM:非聚簇索引
叶子节点存储的是数据文件的指针(记录行的磁盘偏移量)。
Memory 引擎
默认使用 Hash,也可手动选择 USING BTREE。
可在Data Structure Visualization 模拟索引结构
B-Tree(多路平衡树)
以 5 阶 B-Tree 为例:
每个节点最多包含 4 个 key、5 个指针
叶子节点与非叶子节点都存储数据
所有叶子节点在同一层,高度稳定
其特点:
查找次数与树的高度相关
插入、删除时可能发生节点分裂/合并

B+Tree(数据库实际使用的结构)
以 4 阶 B+Tree 为例:
特点:
非叶子节点只存索引,不存数据 → 更高的扇出,更低的树高
数据全部存放在叶子节点
叶子节点之间用链表相连 → 高效范围查询(BETWEEN、>、<)

MySQL 中的 B+Tree 优化(重点)
MySQL 在经典 B+Tree 基础上加入了:
相邻叶子节点的顺序链表(范围查询能力更强)
聚簇索引机制(InnoDB 独有 → 数据组织成 B+Tree)
优势:
范围查询只需叶子链表顺序扫描,不再回到上层节点
更少的树高度(一般 2-4 层,可支持上千万行数据)
为什么 InnoDB 存储引擎选择 B+Tree 索引?
(1)支持范围查询,这一点 Hash 做不到
数据库中大量查询是范围类查询,如:
查某一段时间的数据
查某个 ID 区间
排序、分组
B+Tree 的叶子节点是有序链表,只需一次定位后可顺序扫描,非常高效。
(2)磁盘访问友好,减少随机 I/O
B+Tree 的每个节点能存大量 key(多路),树高度低。
查询时磁盘 I/O 次数少(一般 2~3 次即可定位记录)。
对 OLTP 场景非常友好。
(3)支持排序操作
InnoDB 的索引本身就是有序存储,因此:
ORDER BY key 可以直接利用索引排序
不需要额外的文件排序(避免"Using filesort")
这是 Hash 索引不支持的能力。
4)配合 InnoDB 聚簇索引结构极其高效
InnoDB 主键索引 = 数据本身的物理组织方式。
叶子节点存储整行数据:
查主键 → 一次索引即可找到行
查二级索引 → 先找到主键,再按主键回表
整个流程完美基于 B+Tree 的结构实现。
5)性能稳定(避免退化为链表)
干净的 B+Tree 能保持 高度稳定的 O(log n) 查询性能。
Hash 可能退化(如 hash 冲突严重时),而 B+Tree 不会。
2. Hash 索引
Hash 索引基于哈希表:
Key 经 Hash 函数映射到槽位。
若发生 Hash 冲突,通过链表解决。
特点
等值查询最快(理论上 O(1))
不支持范围查询(因为无序)
不支持排序、分组
不支持部分匹配(LIKE 'abc%')
支持情况
Memory:默认 Hash
InnoDB:有 Adaptive Hash Index(自适应 Hash 索引),由引擎自动创建,不可手动指定
MyISAM:不支持 Hash
适用场景:典型 key-value 查询。
3. 全文索引(Full-text Index)
用于大文本字段(如文章内容)分词搜索,底层基于倒排索引(Inverted Index)。
特点
支持自然语言模式 / 布尔模式
MySQL 8.0+ 支持中文分词(NGRAM)
更适合 title、content、description 等字段
支持情况
MyISAM:早期支持
InnoDB:从 MySQL 5.6 开始支持,现为主流
Memory:不支持
4. R-Tree(空间索引,Spatial Index)
用于 GIS 空间数据:
POINT
LINESTRING
POLYGON
支持空间范围查询,如:
WHERE ST_Within(point, polygon)
特点:
多维区域索引
适合地图、导航、地理计算
支持情况
InnoDB:5.7+ 支持
MyISAM:支持
Memory:不支持
5. 各存储引擎的索引支持情况
| 索引类型 | InnoDB | MyISAM | Memory |
|---|---|---|---|
| B+Tree | ✔(默认,包括聚簇索引与二级索引) | ✔ | ✔(需 USING BTREE) |
| Hash | ✔(自适应 Hash Index,自动生成) | ✘ | ✔(默认) |
| 全文索引(Full-text) | ✔(MySQL 5.6+) | ✔ | ✘ |
| R-Tree(空间索引) | ✔(MySQL 5.7+) | ✔ | ✘ |
6. 索引类型的特性对比
| 索引类型 | 底层结构 | 是否有序 | 支持 = | 支持范围查询 | 典型用途 |
|---|---|---|---|---|---|
| B+Tree | B+Tree | ✔ | ✔ | ✔ | OLTP 查询、排序、范围查找 |
| Hash | 哈希表 | ✘ | ✔ | ✘ | key-value、高速等值查询 |
| 全文索引 | 倒排索引 | 不保证顺序 | 支持全文搜索 | ✘ | 文章、内容检索 |
| R-Tree | 多维空间树 | ✔(空间维度) | ✔ | ✔(空间范围) | GIS、地图位置、几何计算 |
在日常讨论中,如果没有特别说明,"索引"指的就是 B+Tree 索引。
(三)索引分类
MySQL 的索引可以从不同维度进行分类,最常见的是按功能分类与按 InnoDB 存储方式分类。二者都是理解 MySQL 查询优化必不可少的基础。
1. 按功能分类
| 类型 | 特点 | 适用场景 |
|---|---|---|
| 主键索引(PRIMARY KEY) | 索引值唯一,不允许 NULL;每个表只能有一个主键;在 InnoDB 中就是聚簇索引 | 唯一标识一行,例如 id、自增主键 |
| 唯一索引(UNIQUE) | 索引值唯一,但允许多个 NULL;可以有多个唯一索引 | 手机号、身份证号、邮箱等具有唯一性的字段 |
| 普通索引(Index) | 没有唯一性限制,最常见的索引类型 | 常见查询字段,如 name、type、status |
| 全文索引(FULLTEXT) | 用于大文本字段(text、varchar);底层为倒排索引 | 文章内容搜索、日志检索、标题搜索 |
这类索引主要是从 逻辑功能 来划分的,它们的底层结构依然由存储引擎决定。
2. 按 InnoDB 存储方式分类
InnoDB 的索引体系是理解 MySQL 性能的核心。InnoDB 为所有 B+Tree 索引分为两种:
聚簇索引(Clustered Index)
二级索引(Secondary Index)
两类索引的差异直接决定是否回表、查询成本和存储结构。
(1)聚簇索引(Clustered Index)------InnoDB 的核心结构
① 概念
InnoDB 中,整张表的数据按主键顺序组织为一棵 B+Tree。
也就是说:
索引结构 = 数据本身
叶子节点存储整行记录
因此聚簇索引不仅依赖字段特性,更决定了数据的物理存储方式。
②聚簇索引的选取规则
InnoDB 会按照以下优先级选择聚簇索引:
若存在 PRIMARY KEY → 作为聚簇索引
若不存在主键 → 选择第一个 NOT NULL 的 UNIQUE KEY
若都没有 → 自动生成一个隐藏主键 row_id(6 字节)
③聚簇索引的优点
主键查询性能极高
一次 B+Tree 搜索即可直接定位整行,无需回表:
sql
SELECT * FROM user WHERE id = 10;
范围查询高效
由于叶子节点按主键顺序存储并以链表相连:
sql
WHERE id BETWEEN 1000 AND 2000
只需一次定位,然后顺序扫描叶子链表即可。
数据本身有序,有利于排序
例如:
sql
ORDER BY id
无需额外排序操作。
④ 聚簇索引的缺点
| 缺点 | 说明 |
|---|---|
| 主键较大 → 所有二级索引变大 | 因为二级索引的叶子节点都会存主键 |
| 插入不按主键顺序容易导致页分裂 | 主键随机(如 UUID)更明显 |
| 修改主键成本极高 | 需要移动整行数据 |
因此实际开发中推荐使用 自增主键(INT/BIGINT) 作为聚簇索引。
(2) 二级索引(Secondary Index)
除主键外,InnoDB 的所有 B+Tree 索引都是二级索引。
关键特性:
叶子节点 不存放整行记录
存放内容为:
索引列值 + 主键值
因此二级索引查到记录后,仍需要根据主键再次到聚簇索引查出完整数据,这一过程称为 回表(Bookmark Lookup)。
3. 二级索引查询过程(回表过程)
以索引:
sql
CREATE INDEX idx_name ON user(name);
执行查询:
sql
SELECT age FROM user WHERE name = 'Aria';
执行流程:
① 在二级索引 idx_name 中查找到索引项
sql
("Aria", 主键=10)
② 使用主键 pk = 10 再去聚簇索引查整行数据 → 回表
sql
在聚簇索引中查 id = 10
得到完整记录 {id=10, name=Aria, age=20, ...}
这就是回表查询。
回表的影响
二级索引查询会产生额外 I/O
查询结果越多,回表次数越多
大量范围查询时性能明显下降
4. 覆盖索引(Index Covering)------避免回表的核心优化
如果二级索引已经包含查询所需的全部字段,则不需要回表。
例如:
sql
CREATE INDEX idx_name_age (name, age);
SELECT age FROM user WHERE name = 'Aria';
由于索引项就包含 name 和 age:
sql
("Aria", age=20, 主键=10)
因此:
查询可完全在二级索引中完成
不必再去聚簇索引查整行
性能极高
这就是 覆盖索引。
(四)索引语法
在 MySQL 中创建、查看和删除索引的语法相对统一,不同类型的索引仅在关键字上有所区别。
1. 创建索引
sql
CREATE [UNIQUE | FULLTEXT] INDEX index_name
ON table_name (column1, column2);
说明:
UNIQUE:创建唯一索引,保证列值唯一
FULLTEXT:创建全文索引
不写则默认创建普通 B+Tree 索引
可同时指定多个列以创建联合索引
2. 查看索引
sql
SHOW INDEX FROM table_name;
输出包含:
索引名称
列名
是否唯一
是否为主键
Cardinality(基数 → 性能判断重要)
使用的索引类型(BTREE / FULLTEXT / HASH)
3. 删除索引
sql
DROP INDEX index_name ON table_name;
注意:删除主键需使用 ALTER TABLE,因为主键是表结构的一部分。
(五)SQL 性能分析
1. 查看 SQL 执行频率
sql
SHOW GLOBAL STATUS LIKE 'Com_______';
常见统计项:
Com_select:SELECT 执行次数
Com_insert / Com_update / Com_delete:DML 执行次数
可用于判断系统是"读多写少"或"写多读少"。
2. 慢查询日志(Slow Query Log)
用于记录执行时间超过 long_query_time 的 SQL(默认 10 秒)。
开启方式(my.cnf):
sql
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
开启后可通过工具分析:
mysqldumpslow
pt-query-digest
可用于大规模 SQL 优化。
3. profile 分析 SQL 详细耗时
sql
SET profiling = 1;
SHOW PROFILES;
SHOW PROFILE FOR QUERY 1;
可以查看 SQL 的各阶段耗时,例如:
解析 SQL
打开表
执行器处理
发送数据到客户端
适合调试复杂 SQL。
4. EXPLAIN 执行计划(重点)
执行计划用于分析一条 SELECT 的具体执行方式,包括:
使用了哪个索引(key)
扫描的行数(rows)
是否回表(Extra 字段)
是否使用覆盖索引(Using index)
连接顺序(table)
访问类型(type)
常见 type 等级(从好到坏):
sql
system > const > eq_ref > ref > range > index > ALL
ALL:全表扫描(要避免)
ref / range:常见且高效
const:常量查询(主键等值)
EXPLAIN 是索引优化最常用工具。
(六)索引使用
1. 索引效率验证方法
步骤:
(1)执行查询并记录耗时
(2)创建索引
(3)再次执行并对比执行时间
(4)使用 EXPLAIN 检查是否使用了索引
这是最可靠的验证方式。
2. 索引使用原则(重点)
(1)最左前缀法则(联合索引最核心规则)
联合索引 (a, b, c) 的可用情况:
| 条件 | 能否用索引 |
|---|---|
| a | ✔ |
| a + b | ✔ |
| a + b + c | ✔ |
| b | ✘ |
| c | ✘ |
| b + c | ✘ |
原因:B+Tree 的有序性是从最左列开始构建的。
(2)范围查询会导致后续字段失效
sql
(a, b, c):
WHERE a > 10 AND b = 20 → b、c 全部失效
WHERE a = 1 AND b >= 5 → c 失效
因为范围查询(>, <, between)破坏了后续字段的有序性。
推荐:
尽量让范围条件放在最后
或用 >= / <= 替代不确定范围,效果会更好
3. 索引失效情况(第一类)
(1) 对索引列进行运算
sql
where age + 1 = 18
索引失效,因为 MySQL 无法使用原始字段。
应改写:
sql
WHERE age = 17
(2)类型不一致导致隐式转换
sql
WHERE id = '123'
若 id 字段为 int,MySQL 会将索引字段转为字符串 → 索引失效。
改写:
sql
WHERE id = 123
(3)模糊查询
索引可用:
sql
LIKE 'abc%'
索引不可用:
sql
LIKE '%abc'
LIKE '%abc%'
**原因:**没有最左前缀。
解决方式:
使用倒排索引(全文索引)
使用前缀索引
业务重构
4. 索引失效情况(第二类)
(1)OR 条件导致索引同时失效
sql
where id = 1 or age = 30
如果 age 没有索引,则 id 的索引也不会使用。
解决:
为 OR 两侧字段都加索引
或拆分为 UNION 查询:
sql
SELECT * FROM t WHERE id = 1
UNION ALL
SELECT * FROM t WHERE age = 30;
更高效。
(2)数据分布影响(区分度低)
字段选择性(Cardinality)低 → 索引意义不大,比如:
性别(男/女)
状态位(0/1)
地区 ID(大量重复)
MySQL 会自动选择"全表扫描"而不是使用索引。
5. 使用技巧
(1)SQL 提示(Hint)
sql
SELECT * FROM t USE INDEX(idx_x);
SELECT * FROM t FORCE INDEX(idx_x);
SELECT * FROM t IGNORE INDEX(idx_x);
用于调试或强制走某个索引。
(2)覆盖索引
不需要回表 → 性能最高。
sql
SELECT name FROM user WHERE name = 'Tom';
如果 name 是索引,则直接返回。
EXPLAIN 中显示:
sql
Using index
性能极佳。
(3)前缀索引(节省空间)
sql
CREATE INDEX idx_email ON user(email(10));
适用于长字符串字段,如邮箱、URL。
前缀长度建议根据选择性(Cardinality)决定。
6. 单列索引 vs 联合索引
结论:
多条件查询 → 联合索引优于多个单列索引
联合索引同时减少回表(使用覆盖索引)
但联合索引必须满足最左前缀原则
一般推荐:
sql
WHERE a = ? AND b = ? AND c = ?
→ 建联合索引 (a, b, c)
(七)索引设计原则
以下是实际生产中最常使用的索引设计原则:
-
选择区分度高的字段建立索引(如邮箱、手机号)
-
频繁用于 WHERE、ORDER BY、GROUP BY 的列优先建立索引
-
多条件查询优先使用联合索引,不要依赖多个单列索引
-
联合索引遵循最左前缀原则
-
索引列避免使用函数或表达式计算
-
避免为低选择性字段建立索引(如性别、状态位)
-
尽量使用覆盖索引减少回表操作
-
保持主键简单、短小、递增(InnoDB 聚簇索引特性)
-
避免过多索引 → 增加写入成本、占用更多磁盘
-
使用 EXPLAIN 检查索引是否被利用