Стоит ли добавлять индекс в таблицу с частыми изменениями (инсерты, апдейты, делиты)
Что проверяют
Понимаете ли вы, чем индекс платит на записи, и принимаете ли решение по замерам, а не по правилу из статьи. На позиции с C# за вопросом обычно стоит EF Core: индекс объявляется в конфигурации модели и уезжает в миграцию, а последствия достаются базе.
Как отвечать
Объясните механику. Индекс это отдельная структура, которую нужно поддерживать: INSERT дописывает запись в каждый некластерный индекс, DELETE убирает, а UPDATE трогает только те индексы, куда входит изменившаяся колонка. Отсюда правильная постановка вопроса: не насколько часто меняется таблица, а какие именно колонки меняются, сколько индексов уже висит и что мы выигрываем на чтении.
Решение принимается по фактам: план тормозящего запроса, статистика использования индексов, соотношение чтений и записей. Полезные приёмы:
- покрывающий индекс с
INCLUDEвместо нескольких узких; - фильтрованный индекс под конкретный сценарий, например только по активным строкам;
- узкий возрастающий ключ кластерного индекса;
- регулярная чистка дубликатов и никем не используемых индексов.
Хорошая формулировка вывода: лишний индекс стоит примерно одной дополнительной записи, а его отсутствие может стоить полного сканирования на каждом чтении.
Где спотыкаются
Отвечают правилом: таблица часто меняется, значит индексы не нужны. Это ложная экономия, если по той же таблице идут частые выборки, и любой честный ответ упирается в соотношение чтений и записей.
Вешают индекс на каждую колонку из WHERE. В составном индексе порядок колонок важнее их количества, а десяток индексов превращает одну вставку в десяток и заметно раздувает журнал транзакций и резервную копию.
Забывают про блокировки и фрагментацию. Построение индекса на живой таблице без онлайн-режима её блокирует, а случайный идентификатор в роли кластерного ключа приводит к расщеплению страниц на каждой вставке.