Этот движок отличается от MergeTree тем, что удаляет повторяющиеся записи с одинаковым значением ключа сортировки (раздел таблицы ORDER BY, а не PRIMARY KEY).
Дедупликация данных происходит только во время слияния. Слияние выполняется в фоновом режиме в непредсказуемый момент, поэтому заранее рассчитывать на него нельзя. Часть данных может остаться необработанной. Хотя вы можете запустить внеплановое слияние с помощью запроса OPTIMIZE, полагаться на это не стоит, поскольку запрос OPTIMIZE считывает и записывает большой объем данных.
Таким образом, ReplacingMergeTree подходит для фонового удаления дубликатов ради экономии места, но не гарантирует полного отсутствия дубликатов.
Создание таблицы
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
...
) ENGINE = ReplacingMergeTree([ver [, is_deleted]])
[PARTITION BY expr]
[ORDER BY expr]
[PRIMARY KEY expr]
[SAMPLE BY expr]
[SETTINGS name=value, ...]Описание параметров запроса см. в разделе описание оператора.
Параметры ReplacingMergeTree
ver
ver — столбец с номером версии. Тип: UInt*, Date, DateTime или DateTime64. Необязательный параметр.
При слиянии ReplacingMergeTree из всех строк с одинаковым ключом сортировки оставляет только одну:
- Последнюю в выборке, если
verне задан. Выборка — это набор строк из набора частей, участвующих в слиянии. Последней в выборке будет строка из самой недавно созданной части (то есть из последней вставки). Таким образом, после дедупликации для каждого уникального ключа сортировки останется самая последняя строка из самой недавней вставки. - С максимальной версией, если указан
ver. Еслиverодинаков для нескольких строк, то для них будет применяться правило «еслиverне задан», то есть останется строка, вставленная последней.
Пример:
-- без ver - побеждает последняя вставленная строка
CREATE TABLE myFirstReplacingMT
(
`key` Int64,
`someCol` String,
`eventTime` DateTime
)
ENGINE = ReplacingMergeTree
ORDER BY key;
INSERT INTO myFirstReplacingMT Values (1, 'first', '2020-01-01 01:01:01');
INSERT INTO myFirstReplacingMT Values (1, 'second', '2020-01-01 00:00:00');
SELECT * FROM myFirstReplacingMT FINAL;
┌is_deleted
is_deleted — имя столбца, используемого при слиянии для определения того, представляет ли данные в этой строке состояние или строка должна быть удалена; 1 — это строка "удалена", 0 — строка "состояние".
Тип данных столбца — UInt8.
Пример:
-- с ver и is_deleted
CREATE OR REPLACE TABLE myThirdReplacingMT
(
`key` Int64,
`someCol` String,
`eventTime` DateTime,
`is_deleted` UInt8
)
ENGINE = ReplacingMergeTree(eventTime, is_deleted)
ORDER BY key
SETTINGS allow_experimental_replacing_merge_with_cleanup = 1;
INSERT INTO myThirdReplacingMT Values (1, 'first', '2020-01-01 01:01:01', 0);
INSERT INTO myThirdReplacingMT Values (1, 'first', '2020-01-01 01:01:01', 1);
select * from myThirdReplacingMT final;
0 rows in set. Elapsed: 0.003 sec.
-- удалить строки с is_deleted
OPTIMIZE TABLE myThirdReplacingMT FINAL CLEANUP;
INSERT INTO myThirdReplacingMT Values (1, 'first', '2020-01-01 00:00:00', 0);
select * from myThirdReplacingMT final;
┌Секции запроса
При создании таблицы ReplacingMergeTree требуются те же секции, что и при создании таблицы MergeTree.
Устаревший метод создания таблицы
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
...
) ENGINE [=] ReplacingMergeTree(date-column [, sampling_expression], (primary, key), index_granularity, [ver])Все параметры, кроме ver, имеют тот же смысл, что и в MergeTree.
ver— столбец с версией. Необязательный параметр. Описание см. в тексте выше.
Дедупликация во время выполнения запроса & FINAL
Во время слияния ReplacingMergeTree выявляет повторяющиеся строки, используя значения столбцов ORDER BY (применяемых при создании таблицы) как уникальный идентификатор, и сохраняет только строку с наибольшей версией. Однако это обеспечивает лишь отложенную корректность: нет гарантии, что строки будут дедуплицированы, поэтому полагаться на это не следует. В результате запросы могут возвращать неверные результаты, поскольку при их выполнении могут учитываться строки обновления и удаления.
Чтобы получать корректные результаты, пользователям нужно дополнять фоновые слияния дедупликацией во время выполнения запроса и исключением удалённых строк. Это можно сделать с помощью оператора FINAL. Например, рассмотрим следующий пример:
CREATE TABLE rmt_example
(
`number` UInt16
)
ENGINE = ReplacingMergeTree
ORDER BY number
INSERT INTO rmt_example SELECT floor(randUniform(0, 100)) AS number
FROM numbers(1000000000)
0 rows in set. Elapsed: 19.958 sec. Processed 1.00 billion rows, 8.00 GB (50.11 million rows/s., 400.84 MB/s.)Запрос без FINAL возвращает неверное число (точный результат зависит от слияний):
SELECT count()
FROM rmt_example
┌При добавлении FINAL получается правильный результат:
SELECT count()
FROM rmt_example
FINAL
┌Более подробную информацию о FINAL, в том числе о том, как оптимизировать его производительность, см. в нашем подробном руководстве по ReplacingMergeTree.