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

Легковесный оператор 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

  1. Применяется "маска" к затронутым строкам

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

    Маска реализована как скрытая системная колонка _row_exists, которая хранит True для всех видимых строк и False для удаленных. Эта колонка присутствует в части только если некоторые строки в части были удалены. Эта колонка отсутствует, когда у части все значения равны True.

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

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

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

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

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

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

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

    2. Исходя из команд выше, затронутые части мутируют, и жесткие ссылки создаются для незатронутых частей. В случае широких частей колонка _row_exists для каждой строки обновляется, а файлы всех остальных колонок жестко связаны. Для компактных частей все колонки перезаписываются, поскольку они хранятся вместе в одном файле.

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