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

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

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