MySQL建索引需严格校验语法、字段与表名;优先用ALTER TABLE ADD INDEX;复合索引顺序须匹配查询条件;避免冗余索引;大表操作选低峰期;唯一索引承载约束语义;建索引后需ANALYZE TABLE更新统计信息。
CREATE INDEX 语法写错会直接报错,不是静默失败
MySQL 对
的语法很敏感,尤其字段名、表名、索引类型稍有拼写或大小写不一致(在区分大小写的文件系统上),就会报
或
。别急着怀疑权限,先核对三件事:
确认表名完全匹配(含数据库前缀,如
)
或
看字段名是否带反引号、是否真存在
单列索引不用写
,但复合索引里如果漏了括号,比如写成
(缺
),会报语法错误
WHERE 条件里用不到的字段加索引纯属浪费
索引不是越多越好。比如表有
、
、
三个字段,但所有查询都是
,那给
单独建索引几乎没用。真正该做的是:
用
看
列是否命中现有索引
复合索引顺序很重要:
应建
,反过来则可能失效
如果经常
且带
,把
放复合索引末尾能避免 filesort
ALTER TABLE ADD INDEX 比 CREATE INDEX 更常用,但锁表风险更高
虽然
和
效果一样,但实际运维中更倾向后者,因为它是 DDL 标准写法,工具链(如 pt-online-schema-change)也默认识别它。不过要注意:
MySQL(Linux)
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
下载
MySQL 5.6+ 支持
,但加二级索引仍需短暂锁表;5.7+ 对普通 B-tree 索引支持真正的 online DDL,前提是没指定
或
大表加索引务必在低峰期操作,否则
可能被阻塞几秒到几分钟,取决于数据量和磁盘 I/O
不要在从库上直接建索引——主从复制本身不传索引变更,从库索引需手动同步,否则
结果不一致
唯一索引和主键索引不能简单互换
有人看到
字段要查得快,顺手加个
,结果插入重复值时程序直接抛
。这不是性能问题,是语义问题:
是约束 + 索引,会拒绝重复值;
只加速查询,不拦数据
主键(
)自动是唯一且非空的,还隐式作为聚簇索引;普通唯一索引是二级索引,回表成本略高
如果业务本就要求 email 唯一,应该在建表时定义
,而不是事后补索引——DDL 更清晰,应用层错误也更明确
最常被忽略的一点:索引生效依赖统计信息,而
不会自动触发。表数据批量导入后,即使加了索引,优化器也可能因过时的行数估算而选错执行计划。别只盯着建索引,记得跑一次
。
CREATE INDEXERROR 1146 (42S02): Table doesn't existERROR 1054 (42S22): Unknown columnSHOW TABLESmydb.usersDESCRIBE table_nameSHOW COLUMNS FROM table_nameUSING BTREECREATE INDEX idx ON t a,b(a,b)user_idstatuscreated_atWHERE status = ?created_atEXPLAIN SELECT ...keyWHERE status = ? AND created_at > ?INDEX(status, created_at)ORDER BY created_atLIMITcreated_atCREATE INDEX idx ON t(col)ALTER TABLE t ADD INDEX idx(col)ALGORITHM=INPLACELOCK=SHAREDLOCK=EXCLUSIVESELECTSHOW CREATE TABLEemailUNIQUE INDEXDuplicate entry 'x@y.z' for key 'idx_email'UNIQUE INDEXINDEXPRIMARY KEYemail VARCHAR(255) UNIQUEANALYZE TABLEANALYZE TABLE your_table