Перейти к основному содержанию
Перейти к основному содержанию

Легковесное удаление

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

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

GRANT ALTER DELETE ON db.table TO username;

Как легковесные операции DELETE работают внутри ClickHouse

  1. К затронутым строкам применяется «маска»

    Когда выполняется запрос DELETE FROM table ..., ClickHouse сохраняет маску, в которой каждая строка помечается как «существующая» или «удалённая». Эти «удалённые» строки пропускаются при последующих запросах. Однако физическое удаление строк происходит позже при последующих слияниях (merges). Запись этой маски существенно менее ресурсоёмка, чем операция, выполняемая запросом ALTER TABLE ... DELETE.

    Маска реализована как скрытый системный столбец _row_exists, который хранит значение True для всех видимых строк и False — для удалённых. Этот столбец присутствует в куске (part) только в том случае, если какие‑то строки в этом куске были удалены. Столбец отсутствует, когда в куске все значения равны True.

  2. Запросы SELECT преобразуются с учётом маски

    Когда в запросе используется замаскированный столбец, внутренне запрос SELECT ... FROM table WHERE condition дополняется предикатом по _row_exists и преобразуется в:

    SELECT ... FROM table PREWHERE _row_exists WHERE condition
    

    Во время выполнения столбец _row_exists считывается, чтобы определить, какие строки не должны быть возвращены. Если удалено много строк, ClickHouse может определить, какие гранулы можно полностью пропустить при чтении остальных столбцов.

  3. Запросы DELETE преобразуются в запросы ALTER TABLE ... UPDATE

    Оператор DELETE FROM table WHERE condition транслируется в мутацию ALTER TABLE table UPDATE _row_exists = 0 WHERE condition.

    Внутренне эта мутация выполняется в два шага:

    1. Для каждой отдельной части (part) выполняется команда SELECT count() FROM table WHERE condition, чтобы определить, затронута ли эта часть.

    2. На основании результатов команд выше затронутые части мутируются, а для незатронутых создаются жёсткие ссылки (hardlinks). В случае широких частей (wide parts) столбец _row_exists для каждой строки обновляется, а файлы всех остальных столбцов жёстко линкуются. Для компактных частей (compact parts) все столбцы перезаписываются, поскольку они хранятся вместе в одном файле.

    Из описанных выше шагов видно, что легковесный DELETE, использующий технику маскирования, повышает производительность по сравнению с традиционным ALTER TABLE ... DELETE, поскольку не перезаписывает файлы всех столбцов для затронутых частей.