目录
[二、MySQL 索引的主要类型](#二、MySQL 索引的主要类型)
前言
在数据库世界中,索引(Index) 是提升查询效率的"高速公路"。没有索引的查询如同在茫茫人海中逐个寻找目标------耗时且低效;而有了合理设计的索引,MySQL 就能像兰博基尼一样飞驰直达目的地。
本文将系统讲解 MySQL 索引的核心概念、类型、创建与管理方法、使用原则及常见误区,助你构建高性能数据库应用。
一、索引是什么?
类比理解
- 书籍目录:通过"拼音索引"快速定位"张三"在哪一页;
- 字典部首检字表:无需翻遍全书,直接跳转到目标字;
- 数据库索引 :通过 B+ 树等数据结构,快速定位满足
WHERE条件的数据行。
技术本质
索引是独立于数据表的物理结构,存储了:
- 索引列的值(如
email = 'user@example.com') - 指向对应数据行的指针(或主键值)
用途 :将 O(n) 全表扫描 优化为 O(log n) 树查找。
二、MySQL 索引的主要类型
| 类型 | 特点 | 适用场景 |
|---|---|---|
| 普通索引(INDEX) | 允许重复值和 NULL | 加速 WHERE、JOIN、ORDER BY |
| 唯一索引(UNIQUE) | 列值必须唯一(NULL 可多次出现) | 保证业务唯一性(如邮箱、身份证) |
| 主键索引(PRIMARY KEY) | 特殊的唯一索引,不允许 NULL,一张表仅一个 | 表的唯一标识 |
| 组合索引(Composite Index) | 多列联合索引 | 复合查询条件(如 (status, create_time)) |
| 全文索引(FULLTEXT) | 支持关键词搜索(MyISAM / InnoDB 5.6+) | 文章内容、商品描述搜索 |
| 空间索引(SPATIAL) | 用于地理数据(如 POINT、POLYGON) | 地图、LBS 应用 |
三、如何创建索引?
1. 创建普通索引
(1) 使用 CREATE INDEX
sql
-- 在 students 表的 name 列创建索引
CREATE INDEX idx_name ON students (name);
(2) 使用 ALTER TABLE
sql
-- 为 employees 表添加 age 索引
ALTER TABLE employees ADD INDEX idx_age (age);
(3) 建表时直接定义
sql
CREATE TABLE students (
id INT PRIMARY KEY,
name VARCHAR(50),
age INT,
INDEX idx_age (age) -- 普通索引
);
2. 创建唯一索引
(1) 使用 CREATE UNIQUE INDEX
sql
-- 确保 email 唯一
CREATE UNIQUE INDEX idx_email ON employees (email);
(2) 使用 ALTER TABLE
sql
ALTER TABLE employees
ADD CONSTRAINT uk_email UNIQUE (email);
(3) 建表时定义
sql
CREATE TABLE employees (
id INT PRIMARY KEY,
email VARCHAR(100) UNIQUE -- 自动创建唯一索引
);
-- 或显式命名
CREATE TABLE employees (
id INT PRIMARY KEY,
email VARCHAR(100),
UNIQUE uk_email (email)
);
注意:若表中已存在重复值,创建唯一索引会失败!
3. 创建组合索引(多列索引)
sql
-- 查询常按 status 和 create_time 过滤
ALTER TABLE orders
ADD INDEX idx_status_time (status, create_time);
-- 查询示例(能命中索引)
SELECT * FROM orders
WHERE status = 'paid' AND create_time > '2025-01-01';
最左前缀原则 :
组合索引
(A, B, C)能加速以下查询:
WHERE A = ?WHERE A = ? AND B = ?WHERE A = ? AND B = ? AND C = ?
但 不能加速WHERE B = ?或WHERE C = ?。
四、删除索引
sql
-- 方法1:DROP INDEX
DROP INDEX idx_name ON students;
-- 方法2:ALTER TABLE
ALTER TABLE students DROP INDEX idx_name;
-- 删除主键(特殊语法)
ALTER TABLE students DROP PRIMARY KEY;
删除前请确认:
- 该索引是否被重要查询依赖;
- 是否有外键引用(主键不可直接删)。
五、查看索引信息
sql
-- 查看 students 表的所有索引
SHOW INDEX FROM students\G
-- 关键字段解读:
-- Key_name: 索引名称
-- Column_name: 索引列
-- Non_unique: 0=唯一, 1=非唯一
-- Seq_in_index: 列在组合索引中的位置
-- Cardinality: 基数(值越接近行数,选择性越高)
-- Collation: 排序方式(A=升序)
六、索引使用最佳实践
应该建索引的场景
- 频繁作为查询条件的列 (
WHERE user_id = ?) - JOIN 关联字段 (
orders.user_id = users.id) - ORDER BY / GROUP BY 的列
- 需要保证唯一性的字段(用唯一索引)
不适合建索引的场景
- 数据量很小的表(< 1000 行,全表扫描更快)
- 频繁更新的列(索引维护成本高)
- 低选择性字段 (如
gender只有男/女) - 包含大量重复值的列
索引设计黄金法则
| 原则 | 说明 |
|---|---|
| 少而精 | 避免过度索引,每个表通常 3~5 个足够 |
| 覆盖查询 | 尽量让索引包含 SELECT 所需字段(避免回表) |
| 前缀索引 | 对长文本(如 VARCHAR(255))可建前缀索引: INDEX idx_url (url(20)) |
| 避免函数索引 | WHERE YEAR(create_time) = 2025 无法用索引,应改写为范围查询 |
七、索引的代价与权衡
| 优势 | 劣势 |
|---|---|
| 查询速度大幅提升 | 占用额外磁盘空间 |
| 支持快速排序/分组 | INSERT/UPDATE/DELETE 变慢(需维护索引) |
| 保证数据唯一性 | 过多索引导致优化器选择困难 |
经验公式 :
写多读少 → 少建索引;
读多写少 → 合理建索引。
八、高级技巧:如何验证索引是否生效?
使用 EXPLAIN 分析执行计划:
sql
EXPLAIN SELECT * FROM employees WHERE email = 'test@example.com';
关注关键字段:
- type :
const/ref表示命中索引,ALL表示全表扫描; - key: 实际使用的索引名;
- rows: 扫描行数(越小越好);
- Extra : 出现
Using index表示"覆盖索引",性能最优。
小结
"高频查询建索引,唯一约束用 UNIQUE;
组合索引遵左前,小表低选莫乱加;
增删改多慎索引,EXPLAIN 验证是王道!"
合理使用索引,是数据库性能优化的第一步,也是最重要的一步。掌握它,你就掌握了让 MySQL 飞起来的钥匙!