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