Легковесный оператор 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
на конкретной таблице для данного пользователя, выполните следующую команду:
Как работают легковесные DELETE внутри ClickHouse
-
Применяется "маска" к затронутым строкам
Когда выполняется запрос
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 ... UPDATE
Запрос
DELETE 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
, так как не требует переписывания всех файлов колонок для затронутых частей. -