Navicat结构比较工具不识别冗余索引,仅比对索引定义是否一致;需先用sys.schema_redundant_indexes或information_schema查询识别候选冗余索引,再结合人工验证列序、方向、强制引用等语义细节。
navicat 的「结构比较」(structure compare)功能只比对两个数据库对象(如表、视图、索引定义)是否完全一致,它不会分析索引间的逻辑覆盖关系。比如 index idx_a (a) 和 index idx_a_b (a, b) 在结构上是不同的对象,比较工具会把它们标记为“差异项”,而非“冗余项”。它无法回答“哪个该删”,只能告诉你“这两个索引定义不相同”。
真正能识别冗余的,是 MySQL 自带的 sys.schema_redundant_indexes 视图(8.0+)或手动比对 information_schema.STATISTICS。你需要先在源库执行这类查询:
SELECT table_name, index_name, GROUP_CONCAT(column_name ORDER BY seq_in_index) AS colsFROM information_schema.STATISTICS WHERE table_schema = 'your_db'GROUP BY table_name, colsHAVING COUNT(*) > 1;
得到疑似重复索引列表后,再把结果整理成带注释的 SQL 文件,在 Navicat 中用「结构比较」对比「上线前版本」和「上线后版本」的 DDL,确认哪些冗余索引是团队新提交的——而不是原本就存在但一直没被发现的。
sys 视图不可用,必须退回到手工解析 SHOW CREATE TABLE 输出INDEX (a) 是否已被既有的 INDEX (a,b,c) 覆盖团队提交 PR 时可能只改了建表语句,但没动已有索引。这时 Navicat 结构比较会显示「无变化」,你以为安全,其实新字段加了却忘了补联合索引,旧索引反而因查询条件变化变成伪冗余。
INDEX idx_status (status),团队新增 created_at 字段并提交了 WHERE status = ? AND created_at > ? 查询——这个查询实际需要 INDEX (status, created_at),但 idx_status 并未被删除,它从“有效”滑向“低效”,而比较工具完全不提示这种退化performance_schema.table_io_waits_summary_by_index_usage 中 COUNT_STAR = 0 的索引,在比较报告里照样显示为“正常存在”把 sys.schema_redundant_indexes 的输出导出为 CSV,发给 DBA 和开发一起过一遍,再在 Navicat 里打开对应表的「对象信息 → 索引」页,逐个点开每个索引看「列顺序」「方向」「是否唯一」——这些细节决定一个索引是否真能被另一个替代,而比较工具永远跳过这一步。
最常被跳过的动作,是检查那个看似冗余的索引是否被某个 FORCE INDEX 或 ORM 的 queryset.extra() 硬编码调用着。Navicat 看不到应用层,它只管数据库结构。