Ответ
Для добавления индекса в большую таблицу без блокировки DML-операций (INSERT, UPDATE, DELETE) используются специальные неблокирующие режимы, которые зависят от используемой СУБД.
PostgreSQL
В PostgreSQL для этого используется опция CONCURRENTLY
.
CREATE INDEX CONCURRENTLY idx_name ON table_name (column_name);
Ключевые особенности и риски:
- Отсутствие блокировок: Команда не блокирует операции записи в таблицу, позволяя приложению работать в штатном режиме.
- Ресурсоемкость: Процесс занимает больше времени и потребляет больше ресурсов CPU и I/O по сравнению со стандартным
CREATE INDEX
. - Риск неудачи: Если построение индекса завершается с ошибкой, он остается в системе как невалидный (
invalid
). Такой индекс нужно удалить вручную (DROP INDEX CONCURRENTLY idx_name
) и запустить команду заново. - Транзакции: Эту команду нельзя выполнять внутри блока транзакции (
BEGIN...COMMIT
).
MySQL (InnoDB)
В MySQL (для движка InnoDB) используется комбинация ALGORITHM=INPLACE
и LOCK=NONE
.
ALTER TABLE table_name
ADD INDEX idx_name (column_name), ALGORITHM=INPLACE, LOCK=NONE;
Ключевые особенности:
ALGORITHM=INPLACE
: Позволяет избежать создания полной копии таблицы, что значительно ускоряет процесс и снижает нагрузку.LOCK=NONE
: Разрешает параллельное выполнение DML-операций во время создания индекса.- В современных версиях MySQL (5.6+) такое поведение часто является стандартным для
ADD INDEX
, но явное указание параметров является хорошей практикой для предсказуемости.