Легковесный оператор DELETE
Легковесный оператор DELETE
удаляет строки из таблицы [db.]table
, которые соответствуют выражению expr
. Он доступен только для семейства движков таблиц *MergeTree.
Он называется "легковесным DELETE
", чтобы подчеркнуть отличие от команды ALTER TABLE ... DELETE, которая является ресурсозатратным процессом.
Примеры
Легковесный DELETE
не удаляет данные немедленно
Легковесный 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
Удаление больших объёмов данных с помощью легковесного оператора DELETE
может негативно сказаться на производительности запросов SELECT.
Следующие факторы также могут негативно повлиять на производительность легковесного DELETE
:
- Сложное условие
WHERE
в запросеDELETE
. - Если очередь мутаций заполнена множеством других мутаций, это может привести к проблемам с производительностью, поскольку все мутации в таблице выполняются последовательно.
- Затронутая таблица содержит очень большое количество частей данных.
- Наличие большого объема данных в компактных частях. В компактной части все колонки хранятся в одном файле.
Права на удаление
DELETE
требует привилегии ALTER DELETE
. Чтобы разрешить операторы DELETE
на конкретной таблице для заданного пользователя, выполните следующую команду:
Как работают легковесные удаления внутри ClickHouse
-
Применяется "маска" к затронутым строкам
Когда выполняется запрос
DELETE FROM table ...
, ClickHouse сохраняет маску, в которой каждая строка помечается как "существующая" или "удаленная". Эти "удаленные" строки опускаются в последующих запросах. Однако строки фактически удаляются только во время последующих слияний. Запись этой маски намного легче, чем то, что делается запросомALTER TABLE ... DELETE
.Маска реализована как скрытая системная колонка
_row_exists
, которая хранитTrue
для всех видимых строк иFalse
для удаленных. Эта колонка присутствует в части только если некоторые строки в части были удалены. Эта колонка отсутствует, когда у части все значения равныTrue
. -
Запросы
SELECT
преобразуются для включения маскиКогда маскируемая колонка используется в запросе, запрос
SELECT ... FROM table WHERE condition
внутренне дополняется предикатом на_row_exists
и преобразуется в:В момент выполнения колонка
_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
, так как не требует перезаписи файлов всех колонок для затронутых частей. -