UPDATE и DELETE в ClickHouse: mutations, lightweight delete
↑ 3.1 ClickHouse · ← Предыдущая · → Следующая
Зачем это на собесе
Изменение данных в ClickHouse — редкая и дорогая операция; важно знать альтернативы.
Мутации (ALTER TABLE … UPDATE / DELETE)
ALTER TABLE events UPDATE status = 'archived' WHERE ts < '2025-01-01';
ALTER TABLE events DELETE WHERE user_id = 42;- асинхронные (выполняются в фоне), тяжёлые: перезаписывают целые парты, затрагивающие данные;
- не атомарны относительно чтения (часть партов уже изменена);
- выполняются в порядке очереди, статус:
system.mutations(is_done,parts_to_do,latest_fail_reason); - отмена:
KILL MUTATION; - нельзя обновлять столбцы, входящие в ключ сортировки/партиционирования.
Используйте для редких массовых операций (GDPR-удаление, исправление данных), а не для потока изменений.
Лёгкое удаление (lightweight DELETE)
DELETE FROM events WHERE user_id = 42;- сразу помечает строки удалёнными (внутренний маскирующий столбец
_row_exists), запросы перестают их видеть; - физическое удаление происходит позже при слияниях;
- намного быстрее классической мутации, но всё ещё не для частых удалений;
- есть lightweight UPDATE (в новых версиях): быстрые обновления через «патч-парты».
Как обойтись без изменений
| Подход | Описание |
|---|---|
| Append-only | только вставка новых событий; изменения — новыми событиями |
| ReplacingMergeTree | новая версия строки с большей version, читаем последнюю (FINAL/argMax) |
| CollapsingMergeTree | пара «отмена + новая строка» |
| Удаление партиций | DROP PARTITION для устаревших/удаляемых данных, быстро |
| TTL | автоматическое удаление по времени |
Флаг is_deleted | с ReplacingMergeTree |
| Словари/справочники | изменяемые данные вынести в справочник или PostgreSQL |
Проектирование под удаление
- если требуется удалять данные пользователя, продумайте ключи/партиции (например, партиция по тенанту для мелких изолированных клиентов);
- для персональных данных — псевдонимизация и отдельная таблица маппинга;
- храните изменяемые атрибуты (профиль) вне событий и присоединяйте при запросе (JOIN, словарь).
Дедупликация и обновление снимков
Паттерн: CDC из PostgreSQL → ReplacingMergeTree(version, is_deleted); чтение — FINAL или argMax; периодическое OPTIMIZE TABLE ... FINAL (дорого, не запускать бездумно).
Нюансы
OPTIMIZE TABLE FINALпринудительно сливает парты: тяжёлая операция;- мутации в реплицируемых таблицах выполняются на всех репликах и координируются через Keeper;
- большое число одновременных мутаций замедляет слияния.
Вопросы с ответами
Почему ALTER UPDATE в ClickHouse медленный?
Он переписывает целые парты, содержащие изменяемые строки, а не отдельные значения. Работает в фоне и нагружает диск.
Как эффективнее удалить старые данные?
TTL или
DROP PARTITION(метаданные, мгновенно). Для точечного удаления — lightweight DELETE.
Как реализовать «обновляемую» таблицу?
ReplacingMergeTree с версией, чтение через FINAL или
argMax, либо хранить изменяемые данные в PostgreSQL и обогащать через словарь.