3、索引的分类与语法:主键索引、唯一索引、普通索引、全文索引、空间索引
聊到索引的分类,我得先跟你交个底——索引不是越多越好,但选对了类型,性能能翻好几倍。我在项目中见过太多人,一上来就给所有字段加索引,结果写操作慢得像蜗牛。嗯,咱们今天就把这几种索引掰开揉碎了讲清楚。
3.1 索引的五大分类
MySQL里常见的索引类型,说白了就这五种:主键索引、唯一索引、普通索引、全文索引、空间索引。每种都有自己的脾气,用对了地方才是好索引。
核心观点:索引类型的选择,取决于你的查询场景和数据特征。别盲目,也别偷懒。
3.1.1 主键索引(Primary Key)
主键索引,我习惯叫它"身份证索引"。每个表只能有一个,而且不能为空。你想想看,InnoDB存储引擎里,数据本身就是按主键索引组织的——这就是所谓的"聚簇索引"。
-- 创建表时指定主键
CREATE TABLE users (
id INT NOT NULL,
name VARCHAR(50),
PRIMARY KEY (id)
);
-- 或者建表后添加主键
ALTER TABLE users ADD PRIMARY KEY (id);
我的经验:主键最好用自增整数或UUID。用业务字段做主键?我曾经踩过坑——用手机号做主键,结果用户换号时,整张表都要重建,那叫一个酸爽。
3.1.2 唯一索引(Unique Key)
唯一索引,说白了就是"不允许重复"的索引。它允许有空值,但空值也只能有一个。我个人习惯在业务上需要唯一约束的字段上加它,比如邮箱、身份证号。
-- 创建唯一索引
CREATE UNIQUE INDEX idx_email ON users(email);
-- 或者建表时指定
CREATE TABLE users (
id INT,
email VARCHAR(100),
UNIQUE KEY (email)
);
注意:唯一索引和主键索引的区别在于——主键不能为空,唯一索引可以。但如果你在唯一索引列上允许大量NULL值,查询效率会受影响。我遇到过一张表,唯一索引列一半都是NULL,结果查询时走了全表扫描。
3.1.3 普通索引(Index)
普通索引,也叫非唯一索引。它不要求数据唯一,纯粹是为了加速查询。这是最常用的索引类型,也是我平时用得最多的。
-- 创建普通索引
CREATE INDEX idx_name ON users(name);
-- 或者
ALTER TABLE users ADD INDEX idx_name(name);
你想想看,如果一张表有100万条记录,没有索引时查一个名字,得从头扫到尾。有了索引,B+树结构能让你在毫秒级定位到数据。嗯,这就是索引的魅力。
3.1.4 全文索引(Fulltext Index)
全文索引,专门用来对付大文本的模糊搜索。比如文章内容、商品描述这种长文本字段。用LIKE '%关键词%'?那效率低得吓人。全文索引用倒排索引,快得多。
-- 创建全文索引
CREATE FULLTEXT INDEX idx_content ON articles(content);
-- 使用全文索引查询
SELECT * FROM articles
WHERE MATCH(content) AGAINST('数据库优化' IN NATURAL LANGUAGE MODE);
避坑指南:我曾经在一个博客系统里,用LIKE '%关键字%'查文章内容,数据量到10万条时,查询时间飙到了3秒多。后来改成全文索引,直接降到50毫秒。但要注意,全文索引只支持MyISAM和InnoDB(MySQL 5.6+),而且中文分词需要额外配置。
3.1.5 空间索引(Spatial Index)
空间索引,这个用得少,但做GIS(地理信息系统)的朋友肯定不陌生。它专门用来加速空间数据的查询,比如查找某个坐标点附近的所有记录。
-- 创建空间索引
CREATE SPATIAL INDEX idx_location ON stores(location);
-- 查询附近5公里内的店铺
SELECT name, ST_Distance_Sphere(location, POINT(116.4, 39.9)) AS distance
FROM stores
WHERE ST_Distance_Sphere(location, POINT(116.4, 39.9)) < 5000;
说实话,空间索引我在实际项目中只用过一次——帮一个外卖平台做"附近商家"功能。嗯,如果你不做地图相关应用,大概率用不上。
3.2 索引的创建与删除语法
语法这东西,记不住没关系,但得知道怎么查。我整理了一张表,方便你对照使用。
| 操作 | SQL语法 | 说明 |
|---|---|---|
| 创建普通索引 | CREATE INDEX idx_name ON table(column); |
最常用 |
| 创建唯一索引 | CREATE UNIQUE INDEX idx_name ON table(column); |
保证唯一性 |
| 创建全文索引 | CREATE FULLTEXT INDEX idx_name ON table(column); |
用于大文本 |
| 创建空间索引 | CREATE SPATIAL INDEX idx_name ON table(column); |
用于地理数据 |
| 删除索引 | DROP INDEX idx_name ON table; |
注意表名不能省略 |
| 查看索引 | SHOW INDEX FROM table; |
调试时常用 |
重要提醒:删除索引前,一定要确认它没有被其他查询依赖。我曾经在生产环境上删了一个索引,结果某个核心接口的查询时间从10毫秒变成了2秒——嗯,那次被DBA骂得不轻。
3.3 索引选择的核心原则
说了这么多,到底该怎么选?我总结了几条原则,你记一下:
- 主键索引:每个表必须有,推荐自增ID或雪花算法生成的ID。
- 唯一索引:业务上需要唯一约束的字段,比如邮箱、身份证号。
- 普通索引:经常出现在WHERE、JOIN、ORDER BY中的字段。
- 全文索引:大文本字段的模糊搜索,别用LIKE。
- 空间索引:只有做GIS相关开发时才需要。
一句话总结:索引是数据库的"目录",选对了类型,查询效率翻倍;选错了,写操作变慢,磁盘空间暴涨。嗯,这就是我今天想跟你聊的核心。
这张图是我自己画的决策树。你看,左边三个是日常高频使用的,右边两个是特定场景才用。嗯,记住这个结构,面试时也能用上。
最后说一句:索引不是银弹。我见过有人一张表建了20个索引,结果插入一条数据要等5秒。索引要精,不要多。每个索引都要问自己一句:这个索引真的能加速查询吗?