MySQL 索引管理
MySQL 索引管理 的完整教学讲解。
创建索引
单行写法:创建普通索引
CREATE INDEX <索引名> ON <表名>(<列名>[, <列名>...]);
-- 在 email 列上创建索引
CREATE INDEX idx_email ON users(email);
单行写法:创建复合索引
CREATE INDEX <索引名> ON <表名>(<列1>, <列2>[, ...]);
-- 创建多列复合索引
CREATE INDEX idx_status_created ON orders(status, created_at);
单行写法:创建唯一索引
CREATE UNIQUE INDEX <索引名> ON <表名>(<列名>);
-- 创建唯一索引
CREATE UNIQUE INDEX uk_email ON users(email);
单行写法:创建前缀索引
CREATE INDEX <索引名> ON <表名>(<列名>(<长度>));
-- 为长字符串列创建前缀索引
CREATE INDEX idx_name_prefix ON users(username(10));
换行写法:创建全文索引
ALTER TABLE <表名> ADD FULLTEXT INDEX <索引名> (<列名>[, ...]);
-- 为文章标题和内容创建全文索引
ALTER TABLE articles ADD FULLTEXT INDEX ft_content (title, content);
换行写法:创建函数索引(8.0.13+)
CREATE INDEX <索引名> ON <表名>((<表达式>));
-- 为列的小写形式创建函数索引
CREATE INDEX idx_lower_email ON users((LOWER(email)));
换行写法:创建降序索引(8.0+)
CREATE INDEX <索引名> ON <表名>(<列> DESC);
-- 创建降序索引优化倒序查询
CREATE INDEX idx_created_desc ON orders(created_at DESC);
ALTER TABLE 管理索引
单行写法:添加普通索引
ALTER TABLE <表名> ADD INDEX <索引名> (<列名>);
-- 添加普通索引
ALTER TABLE users ADD INDEX idx_age (age);
单行写法:添加唯一索引
ALTER TABLE <表名> ADD UNIQUE INDEX <索引名> (<列名>);
-- 添加唯一索引
ALTER TABLE users ADD UNIQUE INDEX uk_phone (phone);
单行写法:添加主键
ALTER TABLE <表名> ADD PRIMARY KEY (<列名>);
-- 添加主键
ALTER TABLE users ADD PRIMARY KEY (id);
单行写法:设置不可见索引(8.0+)
ALTER TABLE <表名> ALTER INDEX <索引名> INVISIBLE;
-- 隐藏索引用于测试删除影响
ALTER TABLE users ALTER INDEX idx_age INVISIBLE;
单行写法:恢复可见索引
ALTER TABLE <表名> ALTER INDEX <索引名> VISIBLE;
-- 恢复索引可见
ALTER TABLE users ALTER INDEX idx_age VISIBLE;
查看索引
单行写法:查看表索引
SHOW INDEX FROM <表名>;
-- 查看 users 表的索引
SHOW INDEX FROM users;
单行写法:查看表索引带库名
SHOW INDEX FROM <表名> FROM <库名>;
-- 查看指定库的表索引
SHOW INDEX FROM users FROM mydb;
单行写法:查看建表语句含索引
SHOW CREATE TABLE <表名>;
-- 查看建表语句中包含的索引定义
SHOW CREATE TABLE users;
删除索引
单行写法:DROP INDEX 删除
DROP INDEX <索引名> ON <表名>;
-- 删除指定索引
DROP INDEX idx_email ON users;
单行写法:ALTER 删除索引
ALTER TABLE <表名> DROP INDEX <索引名>;
-- 通过 ALTER 删除索引
ALTER TABLE users DROP INDEX idx_age;
单行写法:删除主键
ALTER TABLE <表名> DROP PRIMARY KEY;
-- 删除主键索引
ALTER TABLE users DROP PRIMARY KEY;
单行写法:删除全文索引
ALTER TABLE <表名> DROP INDEX <索引名>;
-- 删除全文索引
ALTER TABLE articles DROP INDEX ft_content;
索引分析
单行写法:查看执行计划
EXPLAIN SELECT <列> FROM <表名> WHERE <条件>;
-- 查看查询执行计划
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
单行写法:分析执行计划
EXPLAIN ANALYZE SELECT <列> FROM <表名> WHERE <条件>;
-- 8.0.18+ 显示实际执行耗时
EXPLAIN ANALYZE SELECT * FROM users WHERE status = 1;
单行写法:查看索引使用情况
SELECT * FROM sys.schema_index_statistics WHERE table_schema = '<库名>';
-- 查看索引的读写统计
SELECT * FROM sys.schema_index_statistics
WHERE table_schema = 'mydb' AND table_name = 'users';
单行写法:查看未使用的索引
SELECT * FROM sys.schema_unused_indexes WHERE object_schema = '<库名>';
-- 查找从未被使用的索引
SELECT * FROM sys.schema_unused_indexes WHERE object_schema = 'mydb';
索引维护
单行写法:分析表更新统计
ANALYZE TABLE <表名>;
-- 重新分析表统计信息
ANALYZE TABLE users;
单行写法:检查表
CHECK TABLE <表名>;
-- 检查表是否有错误
CHECK TABLE users;
单行写法:优化表
OPTIMIZE TABLE <表名>;
-- 优化表回收空间
OPTIMIZE TABLE users;
单行写法:在线添加索引
ALTER TABLE <表名> ADD INDEX <索引名> (<列>), ALGORITHM=INPLACE, LOCK=NONE;
-- 在线添加索引不阻塞读写
ALTER TABLE users ADD INDEX idx_nickname (nickname), ALGORITHM=INPLACE, LOCK=NONE;
单行写法:即时添加列索引(8.0.12+)
ALTER TABLE <表名> ADD INDEX <索引名> (<列>), ALGORITHM=INSTANT;
-- 即时操作不影响数据
ALTER TABLE users ADD INDEX idx_status (status), ALGORITHM=INSTANT;
索引设计原则
单行写法:复合索引最左前缀
CREATE INDEX <索引名> ON <表名>(<高频列>, <范围列>);
-- 高频等值列在前,范围列在后
CREATE INDEX idx_status_age ON users(status, age);
单行写法:覆盖索引避免回表
CREATE INDEX <索引名> ON <表名>(<列1>, <列2>);
-- 索引包含查询所需所有列
CREATE INDEX idx_cover ON orders(user_id, status, total_amount);
单行写法:使用 EXPLAIN 验证类型
EXPLAIN SELECT <列> FROM <表名> WHERE <条件>;
-- 检查 type 列是否为 ref 或 eq_ref
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';