Оператор легковесного DELETE удаляет строки из таблицы [db.]table, соответствующие выражению expr. Он доступен только для таблиц семейства *MergeTree.
DELETE FROM [db.]table [ON CLUSTER cluster] [IN PARTITION partition_expr] WHERE expr;
Это называется “легковесный DELETE”, чтобы отличать его от команды ALTER TABLE … DELETE, которая является ресурсоёмкой операцией.
-- Удаляет все строки из таблицы `hits`, где столбец `Title` содержит текст `hello`
DELETE FROM hits WHERE Title LIKE '%hello%';
Легковесный DELETE реализован как мутация: она помечает строки как удалённые, но не удаляет их физически сразу.
По умолчанию команды DELETE дожидаются завершения пометки строк как удалённых, и только после этого возвращают результат. Это может занять много времени, если объём данных велик. В качестве альтернативы можно запустить удаление асинхронно в фоновом режиме с помощью настройки lightweight_deletes_sync. Если она отключена, оператор DELETE вернётся сразу, но данные могут по-прежнему быть видны в запросах, пока фоновая мутация не завершится.
Мутация не удаляет физически строки, помеченные как удалённые: это произойдёт только во время следующего слияния. В результате возможно, что в течение неопределённого времени данные фактически не будут удалены из хранилища, а лишь помечены как удалённые.
Если вам нужно гарантировать удаление данных из хранилища в предсказуемые сроки, рассмотрите возможность использования настройки таблицы min_age_to_force_merge_seconds. Либо можно использовать команду ALTER TABLE … DELETE. Обратите внимание, что удаление данных с помощью ALTER TABLE ... DELETE может потребовать значительных ресурсов, так как при этом пересоздаются все затронутые части.
Удаление больших объёмов данных
Удаление больших объёмов данных может отрицательно сказаться на производительности ClickHouse. Если вам нужно удалить из таблицы все строки, рассмотрите возможность использовать команду TRUNCATE TABLE.
Если вы ожидаете частых удалений, рассмотрите возможность использовать пользовательский ключ партиционирования. В этом случае можно использовать команду ALTER TABLE ... DROP PARTITION, чтобы быстро удалить все строки, относящиеся к этой партиции.
Ограничения легковесного DELETE
Легковесные DELETE с проекциями
По умолчанию DELETE не работает с таблицами, содержащими проекции. Это связано с тем, что операция DELETE может затрагивать строки в проекции. Однако это поведение можно изменить с помощью настройки MergeTree lightweight_mutation_projection_mode.
Удаление больших объёмов данных с помощью легковесного оператора DELETE может негативно сказаться на производительности запросов SELECT.
На производительность легковесного DELETE также могут негативно влиять следующие факторы:
- Сложное условие
WHERE в запросе DELETE.
- Если очередь мутаций заполнена множеством других мутаций, это может привести к проблемам с производительностью, поскольку все мутации таблицы выполняются последовательно.
- Затронутая таблица содержит очень большое число частей данных.
- Большой объём данных в компактных частях. В компактной части все столбцы хранятся в одном файле.
Для выполнения DELETE требуется привилегия ALTER DELETE. Чтобы разрешить пользователю выполнять операторы DELETE для конкретной таблицы, выполните следующую команду:
GRANT ALTER DELETE ON db.table to username;
Как в ClickHouse внутренне работает легковесный DELETE
-
К затронутым строкам применяется «маска»
Когда выполняется запрос
DELETE FROM table ..., ClickHouse сохраняет маску, в которой каждая строка помечается как «существующая» или «удалённая». Такие «удалённые» строки исключаются из последующих запросов. Однако физически строки удаляются только позже, во время последующих слияний. Запись этой маски гораздо менее затратна, чем выполнение запроса ALTER TABLE ... DELETE.
Маска реализована в виде скрытого системного столбца _row_exists, который хранит True для всех видимых строк и False для удалённых. Этот столбец присутствует в части только если в ней были удалены некоторые строки. Если в части все значения равны True, этот столбец отсутствует.
-
Запросы
SELECT преобразуются с учётом маски
Когда в запросе используется замаскированный столбец, запрос SELECT ... FROM table WHERE condition внутренне дополняется предикатом по _row_exists и преобразуется в:
SELECT ... FROM table PREWHERE _row_exists WHERE condition
Во время выполнения столбец _row_exists считывается, чтобы определить, какие строки не нужно возвращать. Если удалённых строк много, ClickHouse может определить, какие гранулы можно полностью пропустить при чтении остальных столбцов.
-
Запросы
DELETE преобразуются в запросы ALTER TABLE ... UPDATE
DELETE FROM table WHERE condition преобразуется в мутацию ALTER TABLE table UPDATE _row_exists = 0 WHERE condition.
Внутренне эта мутация выполняется в два шага:
-
Для каждой отдельной части выполняется команда
SELECT count() FROM table WHERE condition, чтобы определить, затронута ли эта часть.
-
На основе результатов этих команд затем изменяются затронутые части, а для незатронутых создаются жёсткие ссылки. В случае широких частей столбец
_row_exists обновляется для каждой строки, а файлы всех остальных столбцов связываются жёсткими ссылками. Для компактных частей все столбцы перезаписываются, потому что они хранятся вместе в одном файле.
Из описанных выше шагов видно, что легковесный DELETE, использующий технику маскирования, работает быстрее традиционного ALTER TABLE ... DELETE, потому что не требует перезаписи файлов всех столбцов в затронутых частях.
Последнее изменение 10 июня 2026 г.