ReplacingMergeTree
Движок отличается от MergeTree тем, что он удаляет дублирующиеся записи с одинаковым значением ключа сортировки (ORDER BY
секция таблицы, не PRIMARY KEY
).
Дедупликация данных происходит только во время слияния. Слияние происходит в фоновом режиме в неизвестное время, поэтому вы не можете планировать его. Некоторые данные могут остаться не обработанными. Хотя вы можете выполнить несогласованное слияние с помощью запроса OPTIMIZE
, не стоит на это полагаться, так как запрос OPTIMIZE
будет читать и записывать большое количество данных.
Таким образом, ReplacingMergeTree
подходит для фонов очистки дублирующихся данных с целью экономии места, но он не гарантирует отсутствие дубликатов.
Подробное руководство по ReplacingMergeTree, включая лучшие практики и способы оптимизации производительности, доступно здесь.
Создание таблицы
Для описания параметров запроса см. описание операторов.
Уникальность строк определяется секцией ORDER BY
таблицы, а не PRIMARY KEY
.
Параметры ReplacingMergeTree
ver
ver
— колонка с номером версии. Тип UInt*
, Date
, DateTime
или DateTime64
. Необязательный параметр.
При слиянии ReplacingMergeTree
из всех строк с одинаковым ключом сортировки оставляет только одну:
- Последнюю в выборке, если
ver
не установлен. Выборка — это набор строк в наборе частей, участвующих в слиянии. Самая недавно созданная часть (последняя вставка) будет последней в выборке. Таким образом, после дедупликации останется самая последняя строка из самой недавней вставки для каждого уникального ключа сортировки. - С максимальной версией, если
ver
указан. Еслиver
одинаково для нескольких строк, то будет использоваться правило "еслиver
не указан" для них, т.е. останется самая последняя вставленная строка.
Пример:
is_deleted
is_deleted
— название колонки, используемой во время слияния для определения, представляет ли данные в этой строке состояние или должны быть удалены; 1
— строка "удалена", 0
— строка "состояния".
Тип данных колонки — UInt8
.
is_deleted
может быть включен только при использовании ver
.
Независимо от операции с данными, версия должна увеличиваться. Если две вставленные строки имеют одинаковый номер версии, сохраняется последняя вставленная строка.
По умолчанию ClickHouse сохранит последнюю строку для ключа, даже если эта строка является строкой удаления. Это сделано для того, чтобы любые будущие строки с более низкими версиями могли быть безопасно вставлены, и строка удаления все еще применялась.
Чтобы навсегда удалить такие строки удаления, включите настройку таблицы allow_experimental_replacing_merge_with_cleanup
и либо:
-
Установите настройки таблицы
enable_replacing_merge_with_cleanup_for_min_age_to_force_merge
,min_age_to_force_merge_on_partition_only
иmin_age_to_force_merge_seconds
. Если все части в партиции старшеmin_age_to_force_merge_seconds
, ClickHouse объединит их в одну часть и удалит любые строки удаления. -
Вручную выполните
OPTIMIZE TABLE table [PARTITION partition | PARTITION ID 'partition_id'] FINAL CLEANUP
.
Пример:
Операторы запроса
При создании таблицы ReplacingMergeTree
требуются те же операторы, что и при создании таблицы MergeTree
.
Устаревший метод создания таблицы
Не используйте этот метод в новых проектах и, если возможно, перейдите на метод, описанный выше, в старых проектах.
Все параметры, кроме ver
, имеют то же значение, что и в MergeTree
.
ver
- колонка с версией. Необязательный параметр. Для описания смотрите текст выше.
Дедупликация во время запроса и FINAL
Во время слияния ReplacingMergeTree идентифицирует дублирующиеся строки, используя значения колонок ORDER BY
(используемые для создания таблицы) в качестве уникального идентификатора, и сохраняет только наивысшую версию. Однако это обеспечивает только конечную корректность - он не гарантирует, что строки будут дедуплицированы, и на это не следует полагаться. Поэтому запросы могут давать некорректные ответы из-за включения строк обновления и удаления в запросы.
Для получения правильных ответов пользователи должны дополнить фоновые операции слияния дедупликацией во время запроса и удалением строк. Это можно сделать с помощью оператора FINAL
. Например, рассмотрим следующий пример:
Запрос без FINAL
дает некорректный счет (точный результат будет зависеть от слияний):
Добавление FINAL дает правильный результат:
Для получения дополнительной информации о FINAL
, включая способы оптимизации производительности FINAL
, мы рекомендуем прочитать наше подробное руководство по ReplacingMergeTree.