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

Легковесный оператор DELETE

Легковесное DELETE удаляет строки из таблицы [db.]table, которые соответствуют выражению expr. Оно доступно только для семейства движков таблиц *MergeTree.

DELETE FROM [db.]table [ON CLUSTER cluster] [IN PARTITION partition_expr] WHERE expr;

Оно называется "легковесное DELETE" в контексте контраста с командой ALTER TABLE ... DELETE, которая является ресурсоемким процессом.

Примеры

-- Deletes all rows from the `hits` table where the `Title` column contains the text `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.
  • Если очередь мутаций заполнена многими другими мутациями, это может привести к проблемам с производительностью, так как все мутации на таблице выполняются последовательно.
  • Затронутая таблица имеет очень большое количество частей данных.
  • Наличие большого объема данных в компактных частях. В компактной части все колонки хранятся в одном файле.

Права на удаление

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

GRANT ALTER DELETE ON db.table to username;

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

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

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

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

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

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

SELECT ... FROM table PREWHERE _row_exists WHERE condition

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

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