В каких случаях следует удалять индексы в базе данных?

«В каких случаях следует удалять индексы в базе данных?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Индексы ускоряют чтение, но замедляют запись (INSERT, UPDATE, DELETE) и занимают место. Их стоит удалять в следующих случаях:

🗑️ Основные причины для удаления индекса:

  1. Неиспользуемые индексы – индекс, который не используется оптимизатором запросов для ускорения SELECT или условий WHERE, JOIN, ORDER BY. Он создаёт бесполезные накладные расходы.

    • Как проверить: Используйте системные представления (например, pg_stat_all_indexes в PostgreSQL, sys.dm_db_index_usage_stats в SQL Server).
  2. Дублирующие или избыточные индексы – например, если есть составной индекс (A, B), то индекс только на (A) часто является избыточным, так как первый уже может обслуживать запросы по полю A.

  3. Индексы на часто изменяемые столбцы – если столбцы в индексе часто обновляются, СУБД приходится перестраивать индекс при каждой модификации, что снижает производительность операций записи.

  4. Временные индексы – созданные для разовой оптимизации конкретного запроса или миграции данных, но не нужные в ежедневной работе.

🔍 Пример анализа и удаления в PostgreSQL:

-- Поиск потенциально неиспользуемых индексов (ни разу не прочитанных)
SELECT schemaname, tablename, indexname
FROM pg_stat_all_indexes
WHERE idx_scan = 0 AND schemaname NOT LIKE 'pg_%';

-- Удаление индекса
DROP INDEX CONCURRENTLY idx_user_email; -- CONCURRENTLY не блокирует запись в таблицу

⚠️ Важные предостережения:

  • Всегда анализируйте план запроса (EXPLAIN / EXPLAIN ANALYZE) перед удалением, чтобы убедиться, что индекс действительно не используется для критичных запросов.
  • Удаление индекса — операция DROP INDEX — обычно требует эксклюзивной блокировки таблицы (используйте DROP INDEX CONCURRENTLY в PostgreSQL, ONLINE = ON в SQL Server, если возможно).
  • Рассмотрите возможность замены индекса на более оптимальный (например, замену B-Tree на BRIN для временных рядов).