引言

MySQL支持多种索引类型,每种有不同的特点和适用场景。


一、主键索引(PRIMARY KEY)

1.1 特点

  • 唯一且非空
  • 聚簇索引:数据和索引存在一起
  • 每个表只能有一个主键

1.2 创建

-- 方式1:建表时指定
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50)
);

-- 方式2:后续添加
ALTER TABLE users ADD PRIMARY KEY (id);

1.3 聚簇索引(Clustered Index)

InnoDB的主键索引是聚簇索引

  • 叶子节点存储完整的数据行
  • 表数据按主键顺序存储
B+树结构:
       [10, 20]
      /   |   \
[1→row] [10→row] [20→row]  ← 叶子节点存完整数据

优势

  • 主键查询快(一次IO获取完整数据)
  • 范围查询快(数据有序)

劣势

  • 主键不能太长(影响所有二级索引)
  • 插入乱序会导致页分裂

二、唯一索引(UNIQUE INDEX)

2.1 特点

  • 值必须唯一
  • 允许NULL(但只能有一个NULL)
  • 可以有多个唯一索引

2.2 创建

-- 方式1:建表时
CREATE TABLE users (
    id INT PRIMARY KEY,
    email VARCHAR(100) UNIQUE
);

-- 方式2:单独创建
CREATE UNIQUE INDEX idx_email ON users(email);

-- 方式3:ALTER TABLE
ALTER TABLE users ADD UNIQUE INDEX idx_email (email);

2.3 使用场景

-- 用户名、邮箱、手机号等唯一字段
CREATE UNIQUE INDEX idx_username ON users(username);
CREATE UNIQUE INDEX idx_phone ON users(phone);

三、普通索引(NORMAL INDEX)

3.1 特点

  • 最基本的索引
  • 值可以重复
  • 也称为二级索引(Secondary Index)

3.2 创建

-- 方式1:CREATE INDEX
CREATE INDEX idx_name ON users(name);

-- 方式2:ALTER TABLE
ALTER TABLE users ADD INDEX idx_age (age);

-- 方式3:建表时
CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    INDEX idx_name (name)
);

3.3 二级索引(非聚簇索引)

存储结构

  • 叶子节点存储:索引列值 + 主键值
  • 不存储完整数据行
二级索引B+树:
       [张三, 李四]
      /         \
[name:张三→id:10] [name:李四→id:20]  ← 只存主键id

回表查询

  1. 在二级索引找到主键id=10
  2. 回到主键索引(聚簇索引)找完整数据
SELECT * FROM users WHERE name = '张三';
-- 1. 在idx_name找到id=10
-- 2. 回表到主键索引找完整数据

四、联合索引(Composite Index)

4.1 定义

多个列组合的索引。

CREATE INDEX idx_user_date ON orders(user_id, created_at);

4.2 最左前缀原则

-- 可以使用索引
WHERE user_id = 123;
WHERE user_id = 123 AND created_at > '2024-01-01';

-- 不能使用索引
WHERE created_at > '2024-01-01';  -- 缺少user_id

原因:联合索引按从左到右的顺序排序。


五、全文索引(FULLTEXT INDEX)

5.1 特点

  • 用于文本搜索
  • 支持中文分词(MySQL 8.0+)
  • 只能用于CHAR、VARCHAR、TEXT列

5.2 创建

-- 创建全文索引
CREATE TABLE articles (
    id INT PRIMARY KEY,
    title VARCHAR(200),
    content TEXT,
    FULLTEXT INDEX ft_title_content (title, content)
) ENGINE=InnoDB;

5.3 使用

-- MATCH ... AGAINST
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('MySQL索引');

-- 布尔模式
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('+MySQL -Oracle' IN BOOLEAN MODE);

-- 自然语言模式
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('数据库优化' IN NATURAL LANGUAGE MODE);

5.4 限制

  • 最小搜索长度(默认4个字符)
  • 中文分词需要插件(如ngram)
  • 性能不如专业搜索引擎(Elasticsearch)

六、空间索引(SPATIAL INDEX)

用于地理位置数据(GEOMETRY、POINT等)。

CREATE TABLE locations (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    coordinate POINT NOT NULL,
    SPATIAL INDEX idx_coordinate (coordinate)
);

-- 查询附近的位置
SELECT name FROM locations
WHERE ST_Distance_Sphere(coordinate, ST_GeomFromText('POINT(116.4 39.9)')) < 5000;

七、索引管理

7.1 查看索引

-- 查看表的所有索引
SHOW INDEX FROM users;

-- 查看索引统计
SHOW INDEX FROM users WHERE Key_name = 'idx_email';

7.2 删除索引

-- 方式1:DROP INDEX
DROP INDEX idx_email ON users;

-- 方式2:ALTER TABLE
ALTER TABLE users DROP INDEX idx_email;

-- 删除主键
ALTER TABLE users DROP PRIMARY KEY;

7.3 重建索引

-- 重建索引(优化碎片)
ALTER TABLE users ENGINE=InnoDB;

-- 或
OPTIMIZE TABLE users;

八、索引选择建议

场景索引类型示例
主键主键索引id INT PRIMARY KEY
唯一字段唯一索引email UNIQUE
频繁查询普通索引name, age
多条件查询联合索引(user_id, created_at)
文本搜索全文索引title, content
地理位置空间索引coordinate POINT

九、实战案例

案例1:用户表索引设计

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,        -- 主键索引
    username VARCHAR(50) UNIQUE,              -- 唯一索引
    email VARCHAR(100) UNIQUE,                -- 唯一索引
    phone VARCHAR(20),
    age INT,
    created_at DATETIME,
    INDEX idx_phone (phone),                  -- 普通索引
    INDEX idx_age_created (age, created_at)   -- 联合索引
);

案例2:订单表索引设计

CREATE TABLE orders (
    id INT PRIMARY KEY AUTO_INCREMENT,
    order_no VARCHAR(50) UNIQUE,              -- 唯一索引
    user_id INT,
    status VARCHAR(20),
    created_at DATETIME,
    INDEX idx_user_id (user_id),              -- 普通索引
    INDEX idx_status_created (status, created_at)  -- 联合索引
);

十、总结

核心要点

  1. 主键索引:聚簇索引,数据和索引在一起
  2. 唯一索引:值唯一,可有NULL
  3. 普通索引:二级索引,存索引值+主键
  4. 联合索引:多列组合,最左前缀
  5. 全文索引:文本搜索,MATCH AGAINST
  6. 回表:二级索引查询需要回表到主键索引

记忆口诀

主键索引聚簇型,数据索引存一起,
唯一索引值不重,NULL只能有一个。
普通索引二级称,存储主键不存行,
联合索引多列合,最左前缀要记清。
全文索引搜文本,空间索引查位置。

本文字数:约2,600字 难度等级:⭐⭐⭐(索引进阶)