首页/数据/SQL 速查/找出未使用与冗余索引
性能与执行计划72 条

找出未使用与冗余索引

判断索引是否值得保留:MySQL 用 sys 视图,PostgreSQL 用 pg_stat_user_indexes 的扫描计数。

SQL 速查数据更新于 2026-10-13

谁在用这个索引

判断一个索引值不值得保留,先看有没有被用到:MySQL 有 sys 库里的未使用索引与冗余索引视图,PostgreSQL 用 pg_stat_user_indexes 的扫描计数。这些统计都是累计值,必须结合完整业务周期解读,看到 0 次不能直接删。

基本信息

MySQL 未使用sys.schema_unused_indexes
MySQL 冗余sys.schema_redundant_indexes(被其他索引前缀覆盖等)
PostgreSQLpg_stat_user_indexes 的 idx_scan 排序
统计窗口MySQL 自实例启动累计;PG 自统计重置以来累计
处置流程先评估查询模式,再用不可见索引验证,最后删除

典型使用场景

  • 大表索引过多导致写入变慢,梳理可下线项
  • 加新索引前先检查有没有功能重复的旧索引
  • 定期巡检,把未使用索引列成清单
  • 结合索引体积与使用频率排优先级
  • 配合不可见索引做删前的灰度验证

MySQL 查询

MySQL 查询
-- 实例启动以来没有被用过的索引
SELECT * FROM sys.schema_unused_indexes;

-- 冗余索引:被其他索引的前缀覆盖,或功能重复
SELECT * FROM sys.schema_redundant_indexes;

PostgreSQL 查询

PostgreSQL 查询
-- 按扫描次数升序、索引体积降序,优先看又大又没被用到的
SELECT relname, indexrelname, idx_scan,
       pg_size_pretty(pg_relation_size(indexrelid)) AS size
FROM pg_stat_user_indexes
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC
LIMIT 20;

结果怎么读

指标含义怎么判断
idx_scan索引被扫描的次数长期为 0 才值得怀疑
pg_relation_size索引占用的空间又大又不用,优先级最高
唯一索引承担唯一约束,0 次也不能删先用约束视图排除
冗余索引被其他索引最左前缀覆盖保留覆盖能力更强的那个
统计起点实例启动或统计重置之后窗口越短,结论越不可靠
「未使用」不等于「可以删」:月度报表、季度结算这类周期长的查询在整个统计窗口里可能一次都没出现,删掉后到月末才发现缺索引。删除前先确认业务周期,并留好回退路径。
PostgreSQL 的统计在重启或统计重置后清零,视图也只覆盖用户创建的索引;把统计窗口与业务周期对齐之后,结论才可用。

易错点

  • 按「未使用」直接批量删除:统计窗口未必覆盖完整业务周期,先确认没有周期性查询依赖
  • 忽略唯一索引与约束依赖:即使从未被扫描也不能删,先查约束再决定
  • 只按使用率排序不看体积:宽索引即便用量低,也值得评估换成更窄的形式而不是直接删
  • 用累计值判断当前状态:重启或统计重置后计数归零,需要重新积累一个完整周期
  • 删完不留回退路径:大表重建索引耗时长,删除前记录建索引语句并先用不可见索引验证

数据来源与参考

  • MySQL 8.0 Reference Manual · sys.schema_unused_indexes
  • PostgreSQL Documentation · Monitoring Index Usage
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌