Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Обслуживание индексов и фрагментация
index_maintenance

Обслуживание индексов и фрагментация

Фрагментация индексов, rebuild vs reorganize, мониторинг использования, неиспользуемые индексы

Обслуживание индексов и фрагментация

Индексы требуют обслуживания. Без неё они деградируют: запросы замедляются, место расходуется неэффективно, оптимизатор принимает неверные решения.

#Фрагментация индексов

Фрагментация возникает при частых UPDATE и DELETE:

-- При DELETE строка помечается как удалённая, но место не освобождается сразу DELETE FROM orders WHERE status = 'cancelled'; -- При UPDATE строка может переместиться, оставляя 'дыру' UPDATE orders SET status = 'shipped' WHERE id = 12345;

InnoDB не сразу переиспользует освободившееся место. Страницы становятся разреженными:

  • Физическая фрагментация — данные разбросаны по страницам с 'дырами'
  • Логическая фрагментация — порядок данных в страницах отклоняется от логического порядка B-Tree

Влияние на производительность:

  • Больше I/O — нужно прочитать больше страниц для тех же данных
  • Buffer pool менее эффективен — данные хуже кешируются
  • Последовательное чтение деградирует к случайному

#Обнаружение фрагментации

-- Размер данных vs allocated размер SELECT table_name, ROUND(data_length / 1024 / 1024, 2) AS data_mb, ROUND(data_free / 1024 / 1024, 2) AS free_mb, ROUND(data_free * 100.0 / data_length, 2) AS fragmentation_pct FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'orders';

data_free — количество неиспользуемого (зарезервированного, но пустого) места. Высокий процент (>20-30%) сигнализирует о фрагментации.

#Устранение фрагментации

OPTIMIZE TABLE — перестраивает таблицу и все индексы:

-- Для InnoDB это ALTER TABLE ... ENGINE=InnoDB OPTIMIZE TABLE orders; -- Эквивалентная команда ALTER TABLE orders ENGINE=InnoDB; -- Или ALTER TABLE orders FORCE;

Что происходит:

  1. Создаётся НОВАЯ копия таблицы с нуля
  2. Данные копируются в порядке кластерного индекса
  3. Все вторичные индексы перестраиваются
  4. Старая таблица удаляется

Важно: OPTIMIZE TABLE для InnoDB блокирует таблицу на время выполнения. С MySQL 5.6+ используется online DDL — таблица доступна для чтения/записи, но операция всё равно потребляет CPU, I/O и временное место (копия таблицы).

Когда оптимизировать:

  • После массового DELETE (освободить место)
  • После серии UPDATE, изменивших много строк
  • Планово: раз в месяц/квартал для активно изменяемых таблиц

#Мониторинг использования индексов

Performance Schema отслеживает использование каждого индекса:

-- Статистика по каждому индексу SELECT object_schema, object_name, index_name, count_read, count_write, ROUND(sum_timer_wait / 1000000000000, 3) AS wait_time_s FROM performance_schema.table_io_waits_summary_by_index_usage WHERE object_schema = 'your_db' ORDER BY count_read DESC;

count_read — сколько раз индекс использовался для чтения. count_write — для записи (INSERT, UPDATE, DELETE).

sys.schema_unused_indexes — неиспользуемые индексы:

-- Индексы с count_read = 0 SELECT * FROM sys.schema_unused_indexes WHERE object_schema = 'your_db';

Важные ограничения:

  • Данные накапливаются с момента RESTART сервера
  • UNIQUE и FOREIGN KEY индексы могут не считаться 'используемыми', хотя критичны для целостности
  • Редкие запросы (ежемесячный отчёт) могут не попасть в статистику

#Безопасное удаление индексов

Не удаляйте индексы из schema_unused_indexes немедленно:

-- Шаг 1: Переименовать вместо удаления ALTER TABLE orders RENAME INDEX idx_unused TO idx_unused_backup; -- Шаг 2: Мониторить 1-2 недели -- Проверить slow query log — не появились ли новые медленные запросы -- Проверить EXPLAIN для критичных запросов -- Шаг 3: Если проблем нет — удалить ALTER TABLE orders DROP INDEX idx_unused_backup;

Зачем переименовывать, а не удалять: быстрое восстановление (RENAME INDEX idx_unused_backup TO idx_unused) без перестроения индекса.

#Обновление статистики

-- Обновить статистику кардинальности ANALYZE TABLE orders; -- Проверить результат SHOW INDEX FROM orders; -- Столбец Cardinality должен обновиться

Запускайте ANALYZE TABLE:

  • После OPTIMIZE TABLE (статистика сбрасывается)
  • После массовых INSERT/UPDATE/DELETE (>10% строк)
  • По расписанию для стабильных таблиц (раз в неделю/месяц)

#Практический чеклист обслуживания

  • Ежедневно: мониторинг slow query log, alert на новые медленные запросы
  • Еженедельно: ANALYZE TABLE для активно изменяемых таблиц
  • Ежемесячно: OPTIMIZE TABLE для таблиц с высокой фрагментацией (>20%)
  • Ежеквартально: аудит индексов — удалить неиспользуемые, добавить недостающие
  • При деградации: EXPLAIN ANALYZE проблемных запросов, проверка актуальности статистики

Далее: Кластерные и вторичные индексы InnoDB