mysql如何添加索引_mysql索引创建与使用

来源:这里教程网 时间:2026-02-28 20:47:32 作者:

ALTER TABLE 添加索引时,为什么执行卡住或超时?

常见于大表(千万级以上)直接

ALTER TABLE ADD INDEX
,MySQL 会锁表并重建整张表,期间写入阻塞、查询变慢,甚至触发
Lock wait timeout exceeded
错误。

生产环境优先用
ALGORITHM=INPLACE, LOCK=NONE
(5.6+ 支持),但仅对某些操作生效,比如添加二级索引;主键或全文索引不支持无锁
确认存储引擎:InnoDB 支持大部分在线 DDL,MyISAM 一律全表拷贝锁表 提前在低峰期执行,并监控
SHOW PROCESSLIST
中的
altering table
状态
更稳妥的方式是用
pt-online-schema-change
工具,它通过影子表+触发器实现真正无锁

CREATE INDEX 和 ALTER TABLE ADD INDEX 有什么实际区别?

语义上几乎等价,底层都调用相同 DDL 流程,但使用场景和可读性不同。

CREATE INDEX idx_name ON table_name (col)
只能建索引,不能改表结构,语法更聚焦、意图明确
ALTER TABLE table_name ADD INDEX idx_name (col)
属于表结构变更命令,适合批量操作(比如同时加索引+改列类型)
两者在 InnoDB 中生成的 B+ 树结构、查询行为完全一致,性能无差异 注意:如果索引名已存在,
CREATE INDEX
报错
ERROR 1061 (42000): Duplicate key name
ALTER TABLE ... ADD INDEX
同样报错,不会静默覆盖

WHERE 条件含函数或表达式,索引还能用上吗?

绝大多数情况下不能——MySQL 无法对计算后的结果复用索引的有序性。

错误示例:
WHERE YEAR(create_time) = 2023
create_time
列上的索引失效
正确写法:
WHERE create_time >= '2023-01-01' AND create_time ,可走范围扫描
类似陷阱:
WHERE UPPER(name) = 'ABC'
WHERE col + 1 = 100
,都会跳过索引
例外:MySQL 8.0+ 支持函数索引(
CREATE INDEX idx ON t ((UPPER(name)))
),但需显式创建,且只对指定函数有效

联合索引字段顺序怎么排才不白建?

顺序决定索引能否命中、以及能支持哪些查询模式,核心是「最左前缀匹配」原则。

建了
INDEX idx_a_b_c (a, b, c)
,以下查询可用索引:
WHERE a = ?
WHERE a = ? AND b = ?
WHERE a = ? AND b = ? AND c = ?
WHERE b = ?
WHERE b = ? AND c = ?
无法使用该索引(缺少最左列
a
高选择性列(如用户 ID)放前面,低选择性列(如性别、状态)放后面;排序/分组字段若与 WHERE 共用,也应前置 避免冗余:已有
(a, b)
索引,再单独建
(a)
索引意义不大(除非
a
查询极频繁且
b
值很长,影响索引体积)
索引不是越多越好,每多一个索引就多一份写入开销和磁盘占用。上线前务必用
EXPLAIN
验证实际执行计划,而不是只看是否“有索引”。

相关推荐