MySQL 创建索引主要有两套写法:
? 建表时创建(CREATE TABLE)
? 表存在后添加(ALTER TABLE / CREATE INDEX)
???? 语法:
|
1 2 3 4 |
CREATE TABLE 表名 ( 字段定义..., INDEX 索引名(字段名) ); |
? 示例:
|
1 2 3 4 5 |
CREATE TABLE user ( id BIGINT PRIMARY KEY, age INT, INDEX idx_age(age) ); |
???? 常见场景:
WHERE age = ?
WHERE age > ?
经常用来筛选/排序的字段
唯一索引的作用:保证某个字段的值不重复(比如邮箱、手机号)。
???? 语法:
|
1 2 3 4 |
CREATE TABLE 表名 ( 字段定义..., UNIQUE INDEX 索引名(字段名) ); |
? 示例:
|
1 2 3 4 5 |
CREATE TABLE user ( id BIGINT PRIMARY KEY, email VARCHAR(100), UNIQUE INDEX uk_email(email) ); |
???? 注意:
唯一索引会限制重复插入
插入重复值会报错(Duplicate entry)
主键索引的特点:唯一 + 非空,并且一张表只能有一个。
???? 语法:
|
1 2 3 4 5 |
CREATE TABLE 表名 ( id BIGINT NOT NULL, ..., PRIMARY KEY(id) ); |
? 示例:
|
1 2 3 4 5 |
CREATE TABLE user ( id BIGINT NOT NULL, name VARCHAR(50), PRIMARY KEY(id) ); |
联合索引就是:一个索引里放多个字段。
???? 语法:
|
1 2 3 4 |
CREATE TABLE 表名 ( 字段定义..., INDEX 索引名(字段1, 字段2, 字段3) ); |
? 示例:
|
1 2 3 4 5 6 7 |
CREATE TABLE orders ( id BIGINT PRIMARY KEY, user_id BIGINT, status TINYINT, create_time DATETIME, INDEX idx_user_status_time(user_id, status, create_time) ); |
???? 常见场景:
查询某个用户的某种状态订单,并按时间排序
|
1 2 3 |
SELECT * FROM orders WHERE user_id = 1001 AND status = 1 ORDER BY create_time DESC; |
全文索引用于文本检索,适合文章内容搜索。
???? 语法:
|
1 2 3 4 |
CREATE TABLE 表名 ( 字段定义..., FULLTEXT INDEX 索引名(字段名) ); |
? 示例:
|
1 2 3 4 5 |
CREATE TABLE article ( id BIGINT PRIMARY KEY, content TEXT, FULLTEXT INDEX ft_content(content) ); |
???? 在项目里最常用的就是这一套(上线后优化慢SQL)。
|
1 |
ALTER TABLE user ADD INDEX idx_age(age); |
|
1 |
ALTER TABLE user ADD UNIQUE INDEX uk_email(email); |
|
1 |
ALTER TABLE orders ADD INDEX idx_user_status(user_id, status); |
|
1 |
ALTER TABLE article ADD FULLTEXT INDEX ft_content(content); |
???? 注意:
ALTER TABLE 会修改表结构
大表加索引可能会比较慢(线上要小心)
这个写法更“直观”,专门用来创建索引。
|
1 |
CREATE INDEX idx_age ON user(age); |
|
1 |
CREATE UNIQUE INDEX uk_email ON user(email); |
|
1 |
CREATE INDEX idx_user_status_time ON orders(user_id, status, create_time); |
???? 语法:
|
1 |
DROP INDEX 索引名 ON 表名; |
? 示例:
|
1 |
DROP INDEX idx_age ON user; |
主键索引不是普通索引名,删除方式不同:
|
1 |
ALTER TABLE user DROP PRIMARY KEY; |
|
1 |
SHOW INDEX FROM user; |
|
1 |
SHOW CREATE TABLE user; |
|
1 |
SHOW CREATE TABLE user\G |
???? 常见用途:
怀疑索引没建成功
想确认索引名字到底叫什么
看联合索引的字段顺序
如果字段很长(例如 email / url),可以只取前几个字符建索引节省空间。
|
1 |
CREATE INDEX idx_email_prefix ON user(email(10)); |
???? 注意:
只索引前 10 个字符
区分度可能会下降(要看数据分布)
有索引:
|
1 |
CREATE INDEX idx_a_b_c ON t(a, b, c); |
能命中索引:
|
1 2 3 |
WHERE a = 1 WHERE a = 1 AND b = 2 WHERE a = 1 AND b = 2 AND c = 3 |
? 不容易命中:
|
1 2 3 |
WHERE b = 2 WHERE c = 3 WHERE b = 2 AND c = 3 |
一句话理解:联合索引要从最左列开始连续使用。
强制使用:
|
1 2 |
SELECT * FROM user FORCE INDEX(idx_age) WHERE age = 18; |
忽略索引:
|
1 2 |
SELECT * FROM user IGNORE INDEX(idx_age) WHERE age = 18; |