应先确认数据库版本是否为MySQL 5.7+或MariaDB 10.2+,再通过sys.schema_redundant_indexes快速识别冗余索引,否则需手动比对INFORMATION_SCHEMA.STATISTICS;删索引前必须结合执行计划、慢查询日志及业务场景验证。
查重复索引前先确认 Navicat 连接的是 MySQL 5.7+ 或 MariaDB 10.2+
navicat 本身不直接“分析索引重复性”,它依赖底层数据库的 information_schema 或专用视图(如 sys.schema_redundant_indexes)提供数据。mysql 5.7+ 才内置 sys 库,mariadb 10.2+ 也支持类似机制;低于这个版本,sys.schema_redundant_indexes 查不到,得手动比对 information_schema.statistics。
操作前先在 Navicat 查询窗口运行:
SELECT VERSION();
如果返回 5.6.40 或更低,跳过 sys.schema_redundant_indexes 步骤,直接用统计表手工筛查。
用 sys.schema_redundant_indexes 快速定位冗余索引
这是最省力的方式,但只适用于启用了 sys 库且用户有 SELECT 权限的情况。执行:
SELECT * FROM sys.schema_redundant_indexes WHERE table_schema = 'your_db_name';
结果中每行代表一个被判定为“冗余”的索引,含字段:object_schema、object_name(表名)、redundant_index_name、dominant_index_name(更优的那个索引)、sql_drop_index(建议删除语句)。
-
sql_drop_index是可直接复制执行的 DDL,但别急着跑 —— 先看它是否覆盖了你业务里实际用到的查询条件 - 如果
dominant_index_name是PRIMARY,而redundant_index_name是普通索引,大概率可以删;但如果冗余索引包含WHERE + ORDER BY组合字段,而主键没覆盖,就不能盲目删 - 注意:该视图不会标记“功能等价但字段顺序不同”的索引(比如
(a,b)和(b,a)),这类需人工判断
手动比对 INFORMATION_SCHEMA.STATISTICS 查完全重复或前缀重叠
当 sys 不可用,或想验证更细粒度(比如字段顺序、是否含相同前缀),就得查 INFORMATION_SCHEMA.STATISTICS:
SELECT TABLE_NAME, INDEX_NAME, GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) AS cols FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = 'your_db_name' AND INDEX_NAME != 'PRIMARY' GROUP BY TABLE_NAME, INDEX_NAME ORDER BY TABLE_NAME, cols;
把结果导出成 CSV,在 Excel 里按 TABLE_NAME 分组,观察 cols 列:
- 完全一样 → 真重复(比如两个都叫
idx_user_id_status且字段都是user_id,status) - 一个是另一个的前缀(如
a,bvsa,b,c)→ 前者冗余,除非查询只用前两列且c列值分布极不均匀 - 字段相同但顺序不同(
a,bvsb,a)→ 不算冗余,B+ 树索引对最左前缀敏感,二者适用场景不同
删索引前必须验证执行计划和慢查询日志
即使 sys.schema_redundant_indexes 说某个索引冗余,也不能直接删。真实影响取决于你的查询模式:
- 在 Navicat 中右键表 → “设计表” → 点开“索引”页签,记下待删索引的字段和顺序
- 找最近 24 小时的慢查询日志(或开启
long_query_time=1抓几条典型 SQL),用EXPLAIN对照看是否真用到了这个索引 - 特别留意
ORDER BY、GROUP BY、JOIN条件 —— 有些索引看似冗余,实则支撑排序避免 filesort - 测试环境先执行
DROP INDEX idx_name ON table_name;,再压测关键接口,观察 QPS 和延迟变化
容易忽略的一点:InnoDB 的二级索引自带主键字段,所以 (a) 和 (a,id) 在某些场景下并不等价 —— 后者能覆盖更多查询,前者反而可能触发回表。


















