修改表引擎后SHOW INDEX返回空,是索引被重建丢失而非失效;Navicat切换引擎(如MyISAM→InnoDB)执行ALTER TABLE ENGINE时,默认ALGORITHM=INPLACE不保留原有二级索引,尤其在隐式命名、字符集不匹配或前缀索引校验失败时会静默跳过,仅保留主键和唯一约束索引。

修改表引擎后 SHOW INDEX 返回空,不是失效而是重建丢失
Navicat 中执行「表选项 → 存储引擎」切换(如 MyISAM → InnoDB)时,底层实际运行的是 ALTER TABLE ... ENGINE=InnoDB。这个操作在 MySQL 5.6+ 默认使用 ALGORITHM=INPLACE,但**它不会保留原有索引定义**——尤其是当原表是 MyISAM 且索引未显式命名、或字段类型存在隐式兼容问题时,InnoDB 重建过程中可能跳过二级索引创建,只保留主键和唯一约束索引。
常见表现:SHOW INDEX FROM table_name 结果为空或只剩 PRIMARY,EXPLAIN 显示 key: NULL。这不是“索引失效”,是索引被丢弃了。
- MyISAM 表的 FULLTEXT 索引无法迁移到 InnoDB,会被静默忽略
- 原表含前缀索引(如
INDEX idx_name (name(10))),InnoDB 在某些版本中会因长度校验失败而跳过 - 字段字符集不一致(如 utf8mb3 vs utf8mb4)、collation 不匹配,导致索引重建中断
- Navicat 图形界面切换引擎时,不提示也不校验索引依赖,直接提交 ALTER,风险全由用户承担
ERROR 1215 或外键失败,本质是引擎切换触发元数据重置
当你把 MyISAM 表改成 InnoDB 后立刻加外键报 ERROR 1215: Cannot add foreign key constraint,往往不是外键语法错,而是引擎切换让 MySQL 重置了字段元数据状态:原 MyISAM 创建的字段虽类型相同,但内部标识未被 InnoDB 认作“可索引字段”,即使 SHOW CREATE TABLE 看起来一样。
实操验证方式:SHOW INDEX FROM child_table 查外键字段是否有索引;若无,说明引擎切换后没自动补上——InnoDB 要求外键字段**必须有独立索引**,且不能复用联合索引的非最左列。
- 先手动为外键字段建索引:
ALTER TABLE child_table ADD INDEX fk_idx (foreign_key_col) - 再建外键:
ALTER TABLE child_table ADD FOREIGN KEY (foreign_key_col) REFERENCES parent_table(id) - 别依赖 Navicat “设计表 → 外键”一次性操作,它常把建索引和加约束合并成一条语句,在元数据异常时直接失败
为什么 ANALYZE TABLE 也救不回来?因为索引压根不存在
ANALYZE TABLE 只更新统计信息,对缺失索引完全无效。很多用户还原 + 切引擎后发现查询变慢,第一反应是跑 ANALYZE TABLE,结果 EXPLAIN 还是 type: ALL——此时应立即查 SHOW INDEX,而不是反复分析。
真正要做的只有两件事:确认缺失、手动重建。尤其注意:
- 联合索引顺序必须贴合查询:如果常查
WHERE status = ? AND created_at > ?,索引必须是(status, created_at),反过来就无法利用 - 别用 Navicat 图形界面批量加索引:它生成的语句常漏
USING BTREE,或把UNIQUE KEY错写成UNIQUE,导致 MySQL 解析出错 - 大表加索引务必加
ALGORITHM=INPLACE(MySQL 5.6+)并观察SHOW PROCESSLIST,避免锁表阻塞线上业务
Navicat 17+ 切换引擎后索引识别错误(PostgreSQL 场景)
如果你用 Navicat 17 连 PostgreSQL 并逆向工程后发现索引类型标成 HASH,但实际是 BTREE,这不是引擎切换导致的失效,而是 Navicat 解析系统表 pg_am 时硬编码了 AM OID 映射表,遇到新版 PostgreSQL 的 btree 访问方法名(大小写或拼写变体)就 fallback 成它“认识”的 HASH。
真实类型永远以 SELECT indexdef FROM pg_indexes WHERE tablename = 'xxx' 输出为准。临时规避方法:
- 逆向前在查询窗口执行:
SET search_path TO pg_catalog, public; - 确保 Navicat 连接参数里未启用“只读模式”,否则无法读取系统目录完整字段
- 不要基于 ER 图里的错误类型做 DDL 导出,所有索引定义必须从
pg_indexes或\d+ table_name手动复制


















