Легковесное 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
для конкретной таблицы для данного пользователя, выполните следующую команду:
Как легковесные 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
, так как оно не переписывает все файлы столбцов для затронутых частей. -