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验证实际执行计划,而不是只看是否“有索引”。
