ALTER, которые удаляют данные из таблицы. Прежде всего, к ним относятся запросы вроде ALTER TABLE DELETE и т. д. Выполнение таких запросов создаёт новые изменённые версии частей данных. Это означает, что такие команды приводят к перезаписи целых частей данных для всех данных, которые были вставлены до мутации, а значит — к большому количеству запросов на запись.
При удалении можно избежать такого большого количества запросов на запись, если использовать специализированные движки таблиц, например ReplacingMergeTree или CollapsingMergeTree, вместо стандартного движка таблицы MergeTree.
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 может потребовать значительных ресурсов, так как при этом пересоздаются все затронутые части.
Удаление больших объёмов данных
TRUNCATE TABLE.
Если вы ожидаете частых удалений, рассмотрите возможность использовать пользовательский ключ партиционирования. В этом случае можно использовать команду ALTER TABLE ... DROP PARTITION, чтобы быстро удалить все строки, относящиеся к этой партиции.
Ограничения легковесного DELETE
Легковесные DELETE с проекциями
DELETE не работает с таблицами, содержащими проекции. Это связано с тем, что операция DELETE может затрагивать строки в проекции. Однако это поведение можно изменить с помощью настройки MergeTree lightweight_mutation_projection_mode.
Особенности производительности при использовании легковесного DELETE
DELETE может негативно сказаться на производительности запросов SELECT.
На производительность легковесного DELETE также могут негативно влиять следующие факторы:
- Сложное условие
WHEREв запросеDELETE. - Если очередь мутаций заполнена множеством других мутаций, это может привести к проблемам с производительностью, поскольку все мутации таблицы выполняются последовательно.
- Затронутая таблица содержит очень большое число частей данных.
- Большой объём данных в компактных частях. В компактной части все столбцы хранятся в одном файле.
Разрешения для DELETE
DELETE требуется привилегия ALTER DELETE. Чтобы разрешить пользователю выполнять операторы DELETE для конкретной таблицы, выполните следующую команду:
Как в ClickHouse внутренне работает легковесный DELETE
-
К затронутым строкам применяется «маска»
Когда выполняется запрос
DELETE FROM table ..., ClickHouse сохраняет маску, в которой каждая строка помечается как «существующая» или «удалённая». Такие «удалённые» строки исключаются из последующих запросов. Однако физически строки удаляются только позже, во время последующих слияний. Запись этой маски гораздо менее затратна, чем выполнение запросаALTER TABLE ... DELETE. Маска реализована в виде скрытого системного столбца_row_exists, который хранитTrueдля всех видимых строк иFalseдля удалённых. Этот столбец присутствует в части только если в ней были удалены некоторые строки. Если в части все значения равныTrue, этот столбец отсутствует. -
Запросы
SELECTпреобразуются с учётом маски Когда в запросе используется замаскированный столбец, запросSELECT ... FROM table WHERE conditionвнутренне дополняется предикатом по_row_existsи преобразуется в:Во время выполнения столбец_row_existsсчитывается, чтобы определить, какие строки не нужно возвращать. Если удалённых строк много, ClickHouse может определить, какие гранулы можно полностью пропустить при чтении остальных столбцов. -
Запросы
DELETEпреобразуются в запросыALTER TABLE ... UPDATEDELETE FROM table WHERE conditionпреобразуется в мутациюALTER TABLE table UPDATE _row_exists = 0 WHERE condition. Внутренне эта мутация выполняется в два шага:-
Для каждой отдельной части выполняется команда
SELECT count() FROM table WHERE condition, чтобы определить, затронута ли эта часть. -
На основе результатов этих команд затем изменяются затронутые части, а для незатронутых создаются жёсткие ссылки. В случае широких частей столбец
_row_existsобновляется для каждой строки, а файлы всех остальных столбцов связываются жёсткими ссылками. Для компактных частей все столбцы перезаписываются, потому что они хранятся вместе в одном файле.
DELETE, использующий технику маскирования, работает быстрее традиционногоALTER TABLE ... DELETE, потому что не требует перезаписи файлов всех столбцов в затронутых частях. -
Для каждой отдельной части выполняется команда