UPDATE и DELETE в ClickHouse: mutations, lightweight delete

↑ 3.1 ClickHouse · ← Предыдущая · → Следующая

Желательно~3 мин чтенияУровень: middle

Зачем это на собесе

Изменение данных в 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;
  • большое число одновременных мутаций замедляет слияния.

Вопросы с ответами