> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-8c05c8a2.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Легковесное удаление упрощает процесс удаления данных из базы данных.

# Оператор Lightweight DELETE

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

```sql theme={null}
DELETE FROM [db.]table [ON CLUSTER cluster] [IN PARTITION partition_expr] WHERE expr;
```

Это называется "легковесным `DELETE`" в отличие от команды [ALTER TABLE ... DELETE](/ru/reference/statements/alter/delete), которая является тяжеловесной операцией.

<div id="examples">
  ## Примеры
</div>

```sql theme={null}
-- Удаляет все строки из таблицы `hits`, где столбец `Title` содержит текст `hello`
DELETE FROM hits WHERE Title LIKE '%hello%';
```

<div id="lightweight-delete-does-not-delete-data-immediately">
  ## легковесный `DELETE` не удаляет данные сразу
</div>

легковесный `DELETE` реализован как [мутация](/ru/reference/statements/alter/index#mutations): он помечает строки как удалённые, но не удаляет их физически сразу.

По умолчанию команды `DELETE` дожидаются завершения пометки строк как удалённых перед тем, как вернуть результат. Если данных много, это может занять продолжительное время. В качестве альтернативы можно запустить операцию асинхронно в фоновом режиме с помощью настройки [`lightweight_deletes_sync`](/ru/reference/settings/session-settings#lightweight_deletes_sync). Если она отключена, оператор `DELETE` вернётся сразу, но данные могут оставаться видимыми для запросов, пока не завершится фоновая мутация.

Мутация не удаляет физически строки, помеченные как удалённые: это произойдёт только во время следующего слияния. В результате в течение неопределённого времени данные могут фактически оставаться в хранилище и быть лишь помеченными как удалённые.

Если вам нужно гарантировать удаление данных из хранилища в предсказуемые сроки, рассмотрите возможность использования настройки таблицы [`min_age_to_force_merge_seconds`](/ru/reference/settings/merge-tree-settings#min_age_to_force_merge_seconds). Либо можно использовать команду [ALTER TABLE ... DELETE](/ru/reference/statements/alter/delete). Обратите внимание, что удаление данных с помощью `ALTER TABLE ... DELETE` может потребовать значительных ресурсов, поскольку при этом пересоздаются все затронутые части.

<div id="deleting-large-amounts-of-data">
  ## Удаление больших объёмов данных
</div>

Удаление больших объёмов данных может отрицательно сказаться на производительности ClickHouse. Если вам нужно удалить из таблицы все строки, рассмотрите возможность использования команды [`TRUNCATE TABLE`](/ru/reference/statements/truncate).

Если вы предполагаете, что удаления будут выполняться часто, рассмотрите возможность использования [пользовательского ключа партиционирования](/ru/reference/engines/table-engines/mergetree-family/custom-partitioning-key). Затем можно использовать команду [`ALTER TABLE ... DROP PARTITION`](/ru/reference/statements/alter/partition#drop-partitionpart), чтобы быстро удалить все строки, относящиеся к этой партиции.

<div id="limitations-of-lightweight-delete">
  ## Ограничения легковесного `DELETE`
</div>

<div id="lightweight-deletes-with-projections">
  ### Облегчённые `DELETE` с проекциями
</div>

По умолчанию `DELETE` не работает для таблиц с проекциями. Это связано с тем, что операция `DELETE` может затрагивать строки в проекции. Однако это поведение можно изменить с помощью [настройки MergeTree](/ru/reference/settings/merge-tree-settings) `lightweight_mutation_projection_mode`.

<div id="performance-considerations-when-using-lightweight-delete">
  ## Особенности производительности при использовании облегчённого `DELETE`
</div>

**Удаление больших объёмов данных с помощью облегчённого оператора `DELETE` может негативно сказаться на производительности запросов SELECT.**

На производительность облегчённого `DELETE` также могут негативно влиять следующие факторы:

* Сложное условие `WHERE` в запросе `DELETE`.
* Если очередь мутаций заполнена большим количеством других мутаций, это может привести к проблемам с производительностью, так как все мутации таблицы выполняются последовательно.
* Затронутая таблица содержит очень большое число частей данных.
* Большой объём данных в компактных частях. В компактной части все столбцы хранятся в одном файле.

<div id="delete-permissions">
  ## Разрешения на DELETE
</div>

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

```sql theme={null}
GRANT ALTER DELETE ON db.table to username;
```

<div id="how-lightweight-deletes-work-internally-in-clickhouse">
  ## Как внутри ClickHouse работают легковесные DELETE
</div>

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

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

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

2. **Запросы `SELECT` преобразуются так, чтобы учитывать маску**

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

   ```sql theme={null}
   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`.

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

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

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

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

<div id="related-content">
  ## См. также
</div>

* Блог: [Обновления и удаления в ClickHouse](https://clickhouse.com/blog/handling-updates-and-deletes-in-clickhouse)
