客快物流大数据项目(九十六):ClickHouse的VersionedCollapsingMergeTree深入了解

举报
Lansonli 发表于 2022/12/28 17:30:50 2022/12/28
【摘要】 ​ClickHouse的VersionedCollapsingMergeTree深入了解该引擎继承自 MergeTree 并将折叠行的逻辑添加到合并数据部分的算法中,这个引擎:允许快速写入不断变化的对象状态删除后台中的旧对象状态,这显著降低了存储体积VersionedCollapsingMergeTree 用于相同的目的折叠树 ,但使用不同的折叠算法,允许以多个线程的任何顺序插入数据。 特别...

ClickHouse的VersionedCollapsingMergeTree深入了解

该引擎继承自 MergeTree 并将折叠行的逻辑添加到合并数据部分的算法中,这个引擎:

  • 允许快速写入不断变化的对象状态
  • 删除后台中的旧对象状态,这显著降低了存储体积

VersionedCollapsingMergeTree 用于相同的目的折叠树 ,但使用不同的折叠算法,允许以多个线程的任何顺序插入数据。 特别是, Version 列有助于正确折叠行,即使它们以错误的顺序插入。

相比之下, CollapsingMergeTree 只允许严格连续插入。

一、创建VersionedCollapsingMergeTree引擎表的语法

语法结构

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
    name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
    name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
    ...
) ENGINE = VersionedCollapsingMergeTree(sign, version)
    [PARTITION BY expr]
    [ORDER BY expr]
    [SAMPLE BY expr]
    [SETTINGS name=value, ...]


VersionedCollapsingMergeTree(sign)参数说明

Sign是列名称,必须是Int8类型,用来标志Sign列。Sign列值为1是状态行,为-1是取消行。

二、折叠数据

考虑一种情况,您需要为某个对象保存不断变化的数据。对于一个对象有一行,并在发生更改时更新该行是合理的。但是,对于数据库管理系统来说,更新操作非常昂贵且速度很慢,因为它需要重写存储中的数据。 如果需要快速写入数据,则不能接受更新,但可以按如下顺序将更改写入对象。

使用 Sign 列写入行时。 如果 Sign = 1 这意味着该行是一个对象的状态(让我们把它称为 “state” 行)。 如果 Sign = -1 它指示具有相同属性的对象的状态的取消(让我们称之为 “cancel” 行)。 还可以使用 Version 列,它应该用单独的数字标识对象的每个状态。

例如,我们要计算用户在某个网站上访问了多少页面以及他们在那里的时间。

在某个时间点,我们用用户活动的状态写下面的行:

在稍后的某个时候,我们注册用户活动的变化,并用以下两行写入它。

第一行取消对象(用户)的先前状态。 它应该复制已取消状态的所有字段,除了 Sign.

第二行包含当前状态。因为我们只需要用户活动的最后一个状态行

可以删除,折叠对象的无效(旧)状态。 VersionedCollapsingMergeTree 在合并数据部分时执行此操作。

三、使用示例

创建表:

CREATE TABLE UAct
(
    UserID UInt64,
    PageViews UInt8,
    Duration UInt8,
    Sign Int8,
    Version UInt8
)
ENGINE = VersionedCollapsingMergeTree(Sign, Version)
ORDER BY UserID

插入数据:

INSERT INTO UAct VALUES (4324182021466249494, 5, 146, 1, 1);
INSERT INTO UAct VALUES (4324182021466249494, 5, 146, -1, 1),(4324182021466249494, 6, 185, 1, 2);

我们用两个 INSERT 查询以创建两个不同的数据部分。 如果我们使用单个查询插入数据,ClickHouse将创建一个数据部分,并且永远不会执行任何合并。

获取数据:

SELECT *  FROM UAct

我们在这里看到了什么,折叠的部分在哪里?

我们使用两个创建了两个数据部分 INSERT 查询。

该 SELECT 查询是在两个线程中执行的,结果是行的随机顺序。

由于数据部分尚未合并,因此未发生折叠。 ClickHouse在我们无法预测的未知时间点合并数据部分。

这就是为什么我们需要聚合:

SELECT
    UserID,
    sum(PageViews * Sign) AS PageViews,
    sum(Duration * Sign) AS Duration,
    Version
FROM UAct
GROUP BY UserID, Version
HAVING sum(Sign) > 0;

如果我们不需要聚合,并希望强制折叠,我们可以使用 FINAL 修饰符 FROM

SELECT * FROM UAct FINAL

这是一个非常低效的方式来选择数据。 不要把它用于数据量大的表。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。