Облегчённый оператор 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. - Если очередь мутаций заполнена большим количеством других мутаций, это может привести к проблемам с производительностью, поскольку все мутации над таблицей выполняются последовательно.
- В затронутой таблице очень большое количество кусков данных (data parts).
- Большой объем данных хранится в компактных частях. В компактной части (Compact part) все столбцы хранятся в одном файле.
Права на удаление
Для выполнения DELETE требуется привилегия ALTER DELETE. Чтобы разрешить выполнение операторов DELETE для определённой таблицы и пользователя, выполните следующую команду:
Как легковесные операции DELETE работают внутри ClickHouse
-
К затронутым строкам применяется «маска»
Когда выполняется запрос
DELETE FROM table ..., ClickHouse сохраняет маску, в которой каждая строка помечается как «существующая» или «удалённая». Эти «удалённые» строки пропускаются при последующих запросах. Однако физическое удаление строк происходит позже при последующих слияниях (merges). Запись этой маски существенно менее ресурсоёмка, чем операция, выполняемая запросомALTER TABLE ... DELETE.Маска реализована как скрытый системный столбец
_row_exists, который хранит значениеTrueдля всех видимых строк иFalse— для удалённых. Этот столбец присутствует в куске (part) только в том случае, если какие‑то строки в этом куске были удалены. Столбец отсутствует, когда в куске все значения равны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.Внутренне эта мутация выполняется в два шага:
-
Для каждой отдельной части (part) выполняется команда
SELECT count() FROM table WHERE condition, чтобы определить, затронута ли эта часть. -
На основании результатов команд выше затронутые части мутируются, а для незатронутых создаются жёсткие ссылки (hardlinks). В случае широких частей (wide parts) столбец
_row_existsдля каждой строки обновляется, а файлы всех остальных столбцов жёстко линкуются. Для компактных частей (compact parts) все столбцы перезаписываются, поскольку они хранятся вместе в одном файле.
Из описанных выше шагов видно, что легковесный
DELETE, использующий технику маскирования, повышает производительность по сравнению с традиционнымALTER TABLE ... DELETE, поскольку не перезаписывает файлы всех столбцов для затронутых частей. -