Ответ
Для добавления индекса в большую таблицу без блокировки 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, но явное указание параметров является хорошей практикой для предсказуемости.
Ответ 18+ 🔞
А, ну это же про то, как индекс навесить, чтобы всю эту движуху с данными не останавливать! Да, блядь, классика — база тупит, всё висит, а тебе надо срочно индекс прилепить, чтобы запросы не ебали мозг. Слушай, тут главное — не накосячить, а то можно такую дичь устроить, что потом полгода откатывать.
Ну, короче, в PostgreSQL всё просто, как три копейки, но с подвохом, ёпта. Там есть волшебное слово CONCURRENTLY. Кидаешь его в запрос, и он старается не мешать.
CREATE INDEX CONCURRENTLY idx_name ON table_name (column_name);
Но тут, сука, есть нюансы, на которые надо глаза вылупить:
- Не блокирует: Это главный плюс. Пока индекс строится, твоё приложение может дальше писать, обновлять и удалять записи, как ни в чём не бывало. Не то что раньше, блядь, — повесил индекс и пошёл чай пить на полчаса, пока все операции в очередь встанут.
- Жрёт как не в себя: За эту неблокируемость приходится платить. Процесс будет дольше и сожрёт больше твоего CPU и дискового ввода-вывода. Так что лучше это делать не в час пик, а то все на тебя смотреть будут, как на идиота.
- Может накрыться медным тазом: Вот это самый, блядь, неприятный момент. Если что-то пойдёт не так (а оно может, особенно на живой, ебучей базе), индекс останется в системе, но будет помечен как невалидный,
invalid. И лежит себе, как пизда с ушами, никому не нужный. Его потом вручную выносить надо:DROP INDEX CONCURRENTLY idx_nameи начинать всё заново. Волнение, блядь, на нуле. - Не в транзакцию: Эту команду, сука, нельзя засунуть в
BEGIN...COMMIT. Она сама по себе, как хитрая жопа.
А в MySQL (InnoDB) — своя атмосфера
Там уже другие заклинания. Нужно явно указать, что алгоритм на месте (INPLACE) и блокировок никаких (NONE).
ALTER TABLE table_name
ADD INDEX idx_name (column_name), ALGORITHM=INPLACE, LOCK=NONE;
Что тут важно:
ALGORITHM=INPLACE— это чтобы таблицу целиком не копировать, а то можно овердохуища времени и места потратить. Делает всё аккуратненько, на месте.LOCK=NONE— это святое. Прямая команда: "Не смей, блядь, блокировать запись!".- В новых версиях MySQL это часто и так по умолчанию, но, чувак, лучше явно прописать. Потому что доверия, блядь, ноль — а вдруг он в какой-то момент решит по-старинке сделать и всё заблокирует? Так что перестрахуйся, не ленись.