跳至主要内容
跳至主要内容

ReplacingMergeTree 表引擎

该引擎与 MergeTree 的不同之处在于,它会移除具有相同 排序键 值的重复条目(ORDER BY 表段,而不是 PRIMARY KEY)。

数据去重仅在合并期间发生。合并在后台以未知时间进行,因此无法计划。部分数据可能未被处理。虽然可以使用 OPTIMIZE 查询运行非计划合并,但不要依赖它,因为 OPTIMIZE 查询会读取和写入大量数据。

因此,ReplacingMergeTree 适合在后台清除重复数据以节省空间,但不保证完全消除重复项。

注意

关于 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, ...]

有关请求参数的描述,请参阅 语句描述

注意

行的唯一性由 ORDER BY 表段确定,而不是 PRIMARY KEY

ReplacingMergeTree 参数

ver

ver — 版本号列。类型为 UInt*DateDateTimeDateTime64。可选参数。

在合并时,ReplacingMergeTree 会在所有具有相同排序键的行中保留一个

  • 如果没有设置 ver,则保留选择中的最后一个。选择是参与合并的一组 parts 中的一组行。最近创建的 part(最后一次插入)将是选择中的最后一个。因此,去重后,对于每个唯一的排序键,将保留来自最近一次插入的最后一个行。
  • 如果指定了 ver,则保留具有最大版本的行。如果 ver 对于多行相同,则对它们应用“如果未指定 ver”规则,即保留最近插入的行。

示例

-- without ver - the last inserted 'wins'
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;

┌─key─┬─someCol─┬───────────eventTime─┐
│   1 │ second  │ 2020-01-01 00:00:00 │
└─────┴─────────┴─────────────────────┘


-- with ver - the row with the biggest ver 'wins'
CREATE TABLE mySecondReplacingMT
(
    `key` Int64,
    `someCol` String,
    `eventTime` DateTime
)
ENGINE = ReplacingMergeTree(eventTime)
ORDER BY key;

INSERT INTO mySecondReplacingMT Values (1, 'first', '2020-01-01 01:01:01');
INSERT INTO mySecondReplacingMT Values (1, 'second', '2020-01-01 00:00:00');

SELECT * FROM mySecondReplacingMT FINAL;

┌─key─┬─someCol─┬───────────eventTime─┐
│   1 │ first   │ 2020-01-01 01:01:01 │
└─────┴─────────┴─────────────────────┘

is_deleted

is_deleted — 用于在合并期间确定此行中的数据是表示状态还是要删除的列的名称;1 表示“已删除”行,0 表示“状态”行。

列数据类型 — UInt8

注意

仅当使用 ver 时才能启用 is_deleted

无论对数据进行何种操作,都应增加版本号。如果两个插入的行具有相同的版本号,则保留最后插入的行。

默认情况下,ClickHouse 会保留一个键的最后一个行,即使该行是删除行。这是为了确保将来具有较低版本的任何行都可以安全地插入,并且删除行仍然适用。

要永久删除这些删除行,请启用表设置 allow_experimental_replacing_merge_with_cleanup,并

  1. 设置表设置 enable_replacing_merge_with_cleanup_for_min_age_to_force_mergemin_age_to_force_merge_on_partition_onlymin_age_to_force_merge_seconds。如果分区中的所有 parts 都比 min_age_to_force_merge_seconds 更旧,ClickHouse 会将它们全部合并到一个 part 中,并删除任何删除行。

  2. 或者手动运行 OPTIMIZE TABLE table [PARTITION partition | PARTITION ID 'partition_id'] FINAL CLEANUP

示例

-- with ver and 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.

-- delete rows with is_deleted
OPTIMIZE TABLE myThirdReplacingMT FINAL CLEANUP;

INSERT INTO myThirdReplacingMT Values (1, 'first', '2020-01-01 00:00:00', 0);

select * from myThirdReplacingMT final;

┌─key─┬─someCol─┬───────────eventTime─┬─is_deleted─┐
│   1 │ first   │ 2020-01-01 00:00:00 │          0 │
└─────┴─────────┴─────────────────────┴────────────┘

查询子句

创建 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

┌─count()─┐
│     200 │
└─────────┘

1 row in set. Elapsed: 0.002 sec.

添加 final 会产生正确的结果

SELECT count()
FROM rmt_example
FINAL

┌─count()─┐
│     100 │
└─────────┘

1 row in set. Elapsed: 0.002 sec.

有关 FINAL 的更多详细信息,包括如何优化 FINAL 性能,我们建议阅读我们的 ReplacingMergeTree 详细指南

    © . This site is unofficial and not affiliated with ClickHouse, Inc.