Identifying and Safely Removing Unused or Redundant Indexes in MySQL
Unused or redundant indexes waste storage, slow down write operations, and consume memory. MySQL provides several tools and techniques to safely identify and remove unnecessary indexes without impacting application performance.
a. Using performance_schema.table_io_waits_summary_by_index_usage
• Shows how many times MySQL used each index.
• Indexes with zero or extremely low usage may be candidates for removal.
Example Query:
SELECT *
FROM performance_schema.table_io_waits_summary_by_index_usage
WHERE index_name IS NOT NULL
ORDER BY COUNT_STAR ASC;
b. Checking EXPLAIN Plans
• Run EXPLAIN on frequent queries to see which indexes MySQL actually uses.
c. Using MySQL Enterprise Monitor / Percona Toolkit (pt-index-usage)
• Analyzes query logs to detect indexes that are never used.
• Very accurate for real workloads.
Redundant indexes occur when:
• One index fully covers another.
• Composite indexes start with the same columns as smaller indexes.
Examples:
• INDEX (email) is redundant if INDEX (email, status) exists.
• Duplicate indexes created by mistake.
Query to detect redundant indexes (information_schema):
SELECT TABLE_NAME, INDEX_NAME, COLUMN_NAME, SEQ_IN_INDEX
FROM information_schema.STATISTICS
ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX;
Use Invisible Indexes (MySQL 8.0)
Make the index invisible so the optimizer ignores it:
ALTER INDEX idx_email INVISIBLE;
Monitor system performance:
• Slow queries?
• Missing index warnings?
• Query plans changed?
If everything works fine, safely drop the index.
Drop the index only after testing:
ALTER TABLE users DROP INDEX idx_email;
Before dropping:
• Confirm index usage is very low or zero.
• Ensure EXPLAIN plans do not rely on it.
• Validate application logs for performance changes.
• Keep backups for rollback.
Avoid creating overlapping composite indexes.
Audit indexes periodically (especially on large or high-write tables).
Prefer composite indexes over many single-column indexes.
Use invisible indexes for safety when testing index removal.
By carefully analyzing index usage and testing changes with invisible indexes, you can safely remove redundant or unused indexes while protecting application performance.
You notice a table with 10 indexes — how would you figure out which ones aren't being used at all, and what steps would you take before removing one?
What happens if you drop an index that's not in any query plan but the app team says it's 'needed for future features' — what do you do?
After a recent deploy, our search latency doubled — we just removed an index we thought was unused. How do you debug this?
Your team wants to remove three indexes to save disk space, but the DBA says they might be used in rare joins. How do you validate this without breaking production?
You're optimizing a 2TB orders table with 15 indexes — how do you prioritize which ones to remove when you can't afford to test every combination in production?
How would you design a process to automatically flag and deprecate unused indexes across 50+ microservices without causing silent failures?
We're migrating from MySQL 5.7 to 8.0 and inherited 200+ legacy indexes — how do you architect a multi-quarter plan to clean them up without disrupting 10+ teams?
How would you enforce a policy around index hygiene at scale when different teams own different schemas and have conflicting priorities?