Unused Index - Tìm và dọn dẹp index không sử dụng

Mỗi index đều có chi phí: mỗi INSERT/UPDATE/DELETE phải cập nhật tất cả index liên quan. Index thừa = ghi chậm hơn mà không mang lại lợi ích gì cho đọc.

Hai loại index thừa

Loại 1: Index trùng lặp (overlapping)

Index A: (country, lastname, firstname)
Index B: (country)              → B hoàn toàn thừa! A đã bao phủ → XÓA B
Index C: (country, lastname)    → thừa nếu có A → XÓA C
 
NHƯNG:
Index E: (country, lastname, phone)
Index F: (country, lastname, email)
→ KHÔNG thừa! Phục vụ query khác nhau, không thay thế được nhau

Loại 2: Index không ai dùng - tạo từ lâu, query đã thay đổi, không ai để ý xóa. Mỗi thao tác ghi đều lãng phí tài nguyên cập nhật.

Cách phát hiện

-- MySQL: performance_schema
SELECT object_name, index_name, count_star
FROM performance_schema.table_io_waits_summary_by_index_usage
WHERE object_schema NOT IN ('mysql', 'performance_schema')
  AND index_name IS NOT NULL AND index_name != 'PRIMARY'
ORDER BY count_star ASC;
-- count_star = 0 → ứng viên xóa
 
-- PostgreSQL: pg_stat_all_indexes
SELECT schemaname, tablename, indexrelname, idx_scan, idx_tup_read
FROM pg_stat_all_indexes
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY idx_scan ASC;
-- idx_scan = 0 → ứng viên xóa

Cẩn thận: thống kê chỉ tính từ lần khởi động/reset gần nhất. Index có thể “không dùng” tuần này nhưng quan trọng cho báo cáo cuối tháng → theo dõi ít nhất 1-2 chu kỳ nghiệp vụ đầy đủ trước khi xóa.

Xóa an toàn với Invisible Index (MySQL)

-- Bước 1: Ẩn index thay vì xóa ngay
ALTER TABLE website_visits ALTER INDEX twitter_referrals INVISIBLE;
-- DB không dùng index cho query nữa, nhưng index VẪN TỒN TẠI và được cập nhật
 
-- Bước 2: Theo dõi 1-2 tuần. Không có query nào chậm đi → xóa
DROP INDEX twitter_referrals ON website_visits;
-- Nếu có vấn đề → phục hồi TỨC THÌ (không cần rebuild):
ALTER TABLE website_visits ALTER INDEX twitter_referrals VISIBLE;

Lưu ý ngược: index tồn tại nhưng bị đánh dấu invisible cũng là lý do “database không dùng index của tôi” - kiểm tra SELECT INDEX_NAME, IS_VISIBLE FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_NAME='your_table';

PostgreSQL không hỗ trợ ẩn index - cách an toàn nhất: tạo index mới trước (nếu cần thay thế), rồi xóa index cũ.

Mẹo thực tế: đặt lịch nhắc (mỗi quý / nửa năm) kiểm tra danh sách index không sử dụng - đặc biệt với bảng ghi cao: mỗi index thừa bị xóa đều cải thiện tốc độ ghi ngay lập tức.

Liên quan