Mutations vs Lightweight Ops: сравнение
ClickHouse предлагает четыре механизма изменения данных, каждый с уникальным профилем производительности и ограничениями. Правильный выбор определяет разницу между операцией в миллисекунды и процессом, занимающим часы.
Четыре механизма изменения данных
Правило выбора: иерархия операций
DROP PARTITION >> DELETE FROM (lightweight) >> UPDATE (patch parts) >> ALTER TABLE UPDATE/DELETE (mutations)
Выбирайте наиболее быструю операцию, удовлетворяющую требованиям задачи:
-- 1. Можно удалить целую партицию? -> DROP PARTITION (мгновенно)
ALTER TABLE events DROP PARTITION '202312';
-- 2. Нужно удалить < 10% строк, нет projections? -> lightweight DELETE
DELETE FROM events WHERE user_id = 42;
-- 3. Нужно обновить < 10% строк (26.3 LTS)? -> lightweight UPDATE
UPDATE events SET email = 'redacted' WHERE user_id = 42;
-- 4. Всё остальное: projections, > 10% строк -> mutations
ALTER TABLE events UPDATE email = 'redacted' WHERE toDate(event_time) < '2023-01-01';
ALTER TABLE events DELETE WHERE toDate(event_time) < '2023-01-01';
Мониторинг мутаций через system.mutations
system.mutations отслеживает только тяжёлые мутации (ALTER TABLE UPDATE/DELETE). Lightweight DELETE и UPDATE не отображаются в этой таблице.
-- Активные (незавершённые) мутации:
SELECT
database,
table,
mutation_id,
command,
parts_to_do,
parts_done,
is_done,
create_time,
latest_fail_reason
FROM system.mutations
WHERE table = 'events' AND NOT is_done
ORDER BY create_time DESC;
-- Общий прогресс мутации:
SELECT
mutation_id,
parts_done * 100.0 / (parts_to_do + parts_done) AS progress_pct
FROM system.mutations
WHERE table = 'events' AND NOT is_done;
system.mutations показывает прогресс только для ALTER TABLE UPDATE/DELETE. Lightweight DELETE и lightweight UPDATE (Patch Parts) не регистрируются в system.mutations — они синхронны и не требуют фонового отслеживания.
Отмена и управление мутациями
-- Отмена выполняющейся мутации:
KILL MUTATION WHERE table = 'events' AND mutation_id = 'mutation_1234';
-- Проверка: мутация отменена (is_killed = 1)
SELECT mutation_id, is_done, is_killed
FROM system.mutations
WHERE table = 'events';
-- Синхронное ожидание завершения мутации:
ALTER TABLE events UPDATE ... WHERE ...
SETTINGS mutations_sync = 1; -- ждать завершения на локальной реплике
-- mutations_sync = 2: ждать на всех репликах
Практические сценарии
Сценарий 1: GDPR — удаление данных пользователя
-- 50 пользователей из 100M → lightweight DELETE
DELETE FROM user_events WHERE user_id IN (SELECT user_id FROM gdpr_requests);
Сценарий 2: ETL cleanup — удаление дублей по дате
-- Целая партиция дублей → DROP PARTITION (мгновенно)
ALTER TABLE staging_events DROP PARTITION '20240115';
Сценарий 3: Schema migration — новая колонка с вычисленным значением
-- Все строки таблицы → mutation (нет другого пути)
ALTER TABLE events UPDATE category = multiIf(
event_type = 'purchase', 'revenue',
event_type = 'view', 'engagement',
'other'
) WHERE true;
Сценарий 4: Data correction — исправление PII для конкретных аккаунтов
-- 200 аккаунтов из 10M, таблица без projections → lightweight UPDATE
UPDATE user_events SET phone = 'MASKED' WHERE user_id IN (...);
Ключевые выводы
- Иерархия скорости:
DROP PARTITION(O(1)) >>DELETE FROM(O(parts)) >>UPDATE(O(patch)) >> mutations (O(rows)). ALTER TABLE UPDATE/DELETE— единственный выбор для таблиц с projections и обновления > 10% строк.system.mutationsотслеживает только тяжёлые мутации — lightweight операции там не появляются.KILL MUTATION+is_killed— механизм отмены выполняющейся мутации.mutations_sync = 2ждёт завершения мутации на всех репликах — важно для консистентных схема-миграций.