写点什么

clickhosue 准实时数仓能力探索

作者:水滴
  • 2022 年 10 月 06 日
    广东
  • 本文字数:11108 字

    阅读完需:约 36 分钟

clickhosue准实时数仓能力探索

为什么需要准实时数仓

实时数仓面临着以下挑战:


  • 业务还原复杂:首先某些业务行为时间跨度非常大,例如用户购买行为从加购、下单、支付、收货整个周期可能是一周或一个月,如果需要还原某个时间点业务状态流式处理场景非常复杂;其次是业务多状态可能会在短时间内发生,用户购买行为加购、下单、支付可能只是一分钟内操作完成。

  • 业务关联复杂:一家企业业务存在多种业务主体与业务活动,在数据处理与分析场景中将这些主体之间、主体与活动之间进行关联是一种常态,而这些操作在流是场景成本非常高。

  • 数据复用性差:为了提高数据时效性与数据处理性能,流式处理场景一般不对数据进行落地,因此弱化数据复用性。

  • 历史更新成本高:需要在历史的某个点将值变更,这种场景用流计算的成本非常大。


实时数仓建设过程中有多条路线,比较有代表性的是 Lambda 架构与 Kappa 架构;具体差异大家可以百度,概括来讲就是:


  • Lambda 架构是两路架构两路计算两套逻辑,维护成本高,可以覆盖场景丰富;

  • Kappa 架构简单一套逻辑维护简单,但场景比较单一。


基于还不存在一套技术体系可以完美解决实时数仓场景覆盖丰富度、维护复杂度问题现状,因此探索另外一种可能性:将流失计算引擎处理难度大成本高的场景(复杂业务场景还原、复杂业务关联、数据高复用性、历史数据变更)剥离出来如图,由:


  • 带计算与存储能力

  • 并且数据可以实时入口的 OLAP 引擎 clickhosue 来承接这些场景。



探索哪些能力

对 clickhouse 作为准实时数仓以下能力支持程度进行探索:


  • 数据复用性:为了解决数据重复建设的问题,对数据模型进行分层(ods 原始数据层、dwd 明细层、dim 维度层、dws 轻度汇总层、ads 应用层),提高数据复用性。

  • 分钟级数据时效性:数据从上游(flink、spark、kafka 等)同步到各层(ods、dwd、dim、dws)在一分钟内完成;这里只探索理论上可能性,也就是使用 clickhouse 提供的 view,主要是 MATERIALIZED view 与 live view,还有 MergeTree Engine Family 的各种表引擎对提高数据时效可行性验证 。

  • 快速查询响应:只探索理论上可能性,也就是使用 clickhouse 提供的 view,主要是 MATERIALIZED view 与 live view,还有 MergeTree Engine Family 的各种表引擎对数据预处理与折叠(cube),对提高查询响应速度可行性验证。

  • 实时数据写入:使用 CollapsingMergeTree 与 VersionedCollapsingMergeTree 表引擎承接上游(flink、spark、kafka 等)实时数据写入,ReplacingMergeTree 表引擎对实时数据写入存在数据丢失情况进行数据回补。

  • 维度缓慢变化解决方案可行性:使用快照表与历史拉链表解决不同场景的维度缓慢变化可行性。


上游(flink、spark、kafka 等)如何写入的实践放到下个专题数据时效性与快速查询响应在大数据与极限环境的性能验证放到下个专题

场景与模型设计

这里使用一个简化的泛零售业务场景,参与业务主体只有门店与会员,产生业务活动是销售订单。而且只是正向业务过程,不包括逆向业务过程。


销售订单事实表:是累积快照事实表,订单实体某个实例(某行)不断更新,同时一个实例存储多个业务过程日期如下表:


实践

ods

首先使用 VersionedCollapsingMergeTree 引擎创建 ods 层订单表承接上游(flink、spark、kafka 等)对源数据变更(binlog)实时捕获写入。


订单事实表是累积快照事实表,订单数据不断更新,如订单状态在下单、成单、完成支付等多个状态之间变更,使用 VersionedCollapsingMergeTree 引擎通过 Versione 属性(根据订单状态生成 Versione,如 1:下单;2:成单;3:完成支付 )解决因为上游实时数据写入 clickhouse 可能存在数据丢失与乱序问题,导致数据不一致问题,如同一个订单因为下单状态数据后写入,覆盖掉成单状态数据(使用 CollapsingMergeTree 引擎就会存在这个问题)。


创建 ods 订单表


CREATE TABLE IF NOT EXISTS test.ods_real_time_order (    order_code String COMMENT '订单编码',    order_amt Decimal32(2) COMMENT '订单金额',    order_status String COMMENT '订单状态',    order_date DateTime COMMENT '下单日期',    order_rec_date DateTime COMMENT '接单日期',    order_com_date DateTime COMMENT '成单日期',    shop_code String COMMENT '门店编码',    member_code String COMMENT '会员编码',    sign Int8,    version UInt8) ENGINE = VersionedCollapsingMergeTree(sign, version)PARTITION BY shop_codeORDER BY order_codeSETTINGS index_granularity = 8192;
复制代码


会员 m_001 在 2022-10-01 00:00:00 在门店 s_0001 下一张订单号为 o_0001 的销售订单。


INSERT INTO test.ods_real_time_order Values ('o_0001', 10.05,'下单','2022-10-01 00:00:00',null,null,'s_0001','m_0001',1,1);
复制代码


门店 s_0001 的商品库存充裕,订单号为 o_0001 订单在 2022-10-01 00:00:01,状态修改为“成单”


INSERT INTO test.ods_real_time_order Values ('o_0001', 10.05,'下单','2022-10-01 00:00:00',null,null,'s_0001','m_0001',-1,1),('o_0001', 10.05,'成单','2022-10-01 00:00:00','2022-10-01 00:00:01',null,'s_0001','m_0001',1,2);
复制代码


Sign = 1 这意味着该行是一个对象的状态(让我们把它称为 “state” 行)。 如果 Sign = -1 它指示具有相同属性的对象的状态的取消(让我们称之为 “cancel” 行)。 Version 列有助于正确折叠行,即使它们以错误的顺序插入 ,ClickHouse 合并数据部分时,它会删除具有相同主键和 Version 但 Sign 值不同的一对行, 行的顺序并不重要。相比之下, CollapsingMergeTree 只允许严格连续插入。


获取数据:


select * from test.ods_real_time_order;
Query id: 6b72f0fc-4cd8-4121-b087-31da01fff9e4
┌─order_code─┬─order_amt─┬─order_status─┬──────────order_date─┬──────order_rec_date─┬──────order_com_date─┬─shop_code─┬─member_code─┬─sign─┬─version─┐│ o_0001 │ 10.05 │ 下单 │ 2022-10-01 00:00:00 │ 1970-01-01 08:00:00 │ 1970-01-01 08:00:00 │ s_0001 │ m_0001 │ -1 │ 1 ││ o_0001 │ 10.05 │ 成单 │ 2022-10-01 00:00:00 │ 2022-10-01 00:00:01 │ 1970-01-01 08:00:00 │ s_0001 │ m_0001 │ 1 │ 2 │└────────────┴───────────┴──────────────┴─────────────────────┴─────────────────────┴─────────────────────┴───────────┴─────────────┴──────┴─────────┘┌─order_code─┬─order_amt─┬─order_status─┬──────────order_date─┬──────order_rec_date─┬──────order_com_date─┬─shop_code─┬─member_code─┬─sign─┬─version─┐│ o_0001 │ 10.05 │ 下单 │ 2022-10-01 00:00:00 │ 1970-01-01 08:00:00 │ 1970-01-01 08:00:00 │ s_0001 │ m_0001 │ 1 │ 1 │└────────────┴───────────┴──────────────┴─────────────────────┴─────────────────────┴─────────────────────┴───────────┴─────────────┴──────┴─────────┘
3 rows in set. Elapsed: 0.003 sec.
复制代码


我们在这里看到了什么,我们使用两个创建了两个数据部分 INSERT 查询。 该 SELECT 查询是在两个线程中执行的,结果是行的随机顺序。 由于数据部分尚未合并,因此未发生折叠。 ClickHouse 在我们无法预测的未知时间点合并数据部分


可以使用集合方式


SELECT    order_code,    sum(order_amt * sign) AS order_amtFROM test.ods_real_time_orderGROUP BY order_codeHAVING sum(sign) > 0
Query id: 565a15d4-adad-4d35-815c-0ac3d80ea30a
┌─order_code─┬─order_amt─┐│ o_0001 │ 10.05 │└────────────┴───────────┘
1 row in set. Elapsed: 0.003 sec.
复制代码


如果我们不需要聚合并想要强制进行折叠,我们可以在 FROM 从句中使用 FINAL 修饰语。


SELECT *FROM test.ods_real_time_orderFINAL
Query id: b5abebef-079e-4cb8-9fdb-7e0dedd6c9e6
┌─order_code─┬─order_amt─┬─order_status─┬──────────order_date─┬──────order_rec_date─┬──────order_com_date─┬─shop_code─┬─member_code─┬─sign─┬─version─┐│ o_0001 │ 10.05 │ 成单 │ 2022-10-01 00:00:00 │ 2022-10-01 00:00:01 │ 1970-01-01 08:00:00 │ s_0001 │ m_0001 │ 1 │ 2 │└────────────┴───────────┴──────────────┴─────────────────────┴─────────────────────┴─────────────────────┴───────────┴─────────────┴──────┴─────────┘
复制代码


或者使用 optimize 触发 merge


OPTIMIZE TABLE test.ods_real_time_order FINAL
Query id: 44f5cb3c-d57d-4e0b-b180-0c967e35999d
Ok.
0 rows in set. Elapsed: 0.004 sec.
instance-vx60mbtu :) select * from test.ods_real_time_order;
SELECT *FROM test.ods_real_time_order
Query id: 1eb9cd81-1544-433f-935f-2c74f2898352
┌─order_code─┬─order_amt─┬─order_status─┬──────────order_date─┬──────order_rec_date─┬──────order_com_date─┬─shop_code─┬─member_code─┬─sign─┬─version─┐│ o_0001 │ 10.05 │ 成单 │ 2022-10-01 00:00:00 │ 2022-10-01 00:00:01 │ 1970-01-01 08:00:00 │ s_0001 │ m_0001 │ 1 │ 2 │└────────────┴───────────┴──────────────┴─────────────────────┴─────────────────────┴─────────────────────┴───────────┴─────────────┴──────┴─────────┘
1 row in set. Elapsed: 0.002 sec.
复制代码


订单号为 o_0001 订单在 2022-10-01 00:00:02 完成支付后,上游在写入数据出现了数据丢失(可能是没有捕捉到 update 事务,也可能因为 bug),丢失了 version=2 的 sign=-1 数据数据,只写入 version=3 的 sign=1 数据


INSERT INTO test.ods_real_time_order Values ('o_0001', 10.05,'完成支付','2022-10-01 00:00:00','2022-10-01 00:00:01','2022-10-01 00:00:02','s_0001','m_0001',1,3);
复制代码


再看下数据


SELECT *FROM test.ods_real_time_order
Query id: 8df80da1-8aed-4ac0-b04e-a95e41474e10
┌─order_code─┬─order_amt─┬─order_status─┬──────────order_date─┬──────order_rec_date─┬──────order_com_date─┬─shop_code─┬─member_code─┬─sign─┬─version─┐│ o_0001 │ 10.05 │ 成单 │ 2022-10-01 00:00:00 │ 2022-10-01 00:00:01 │ 1970-01-01 08:00:00 │ s_0001 │ m_0001 │ 1 │ 2 │└────────────┴───────────┴──────────────┴─────────────────────┴─────────────────────┴─────────────────────┴───────────┴─────────────┴──────┴─────────┘┌─order_code─┬─order_amt─┬─order_status─┬──────────order_date─┬──────order_rec_date─┬──────order_com_date─┬─shop_code─┬─member_code─┬─sign─┬─version─┐│ o_0001 │ 10.05 │ 完成支付 │ 2022-10-01 00:00:00 │ 2022-10-01 00:00:01 │ 2022-10-01 00:00:02 │ s_0001 │ m_0001 │ 1 │ 3 │└────────────┴───────────┴──────────────┴─────────────────────┴─────────────────────┴─────────────────────┴───────────┴─────────────┴──────┴─────────┘
复制代码


此场景就算使用 optimize 触发 merge 后,还是会同个订单号有多条数据(订单状态不一致),这个问题我们放在 dwd 层解决。

dwd

使用 ReplacingMergeTree 引擎创建 dwd 订单表,主要是为了对 ods 层数据写入时因为各种情况导致订单数据重复进行兜底;在使用 clickhouse 过程中,需要对很大情况进行兜底,如上面提到 merge 在不可预知情况发生;再如 clickhouse 的 MATERIALIZED VIEW 的数据同步只发生在 insert 情况;这些都会加大数据开发难道,同时也增加数据处理、分析复杂性。


ENGINE = ReplacingMergeTree([ver]),在数据合并的时候,ReplacingMergeTree 从所有具有相同排序键的行中选择一行留下:如果 ver 列未指定,保留最后一条;如果 ver 列已指定,保留 ver 值最大的版本。数据的去重只会在数据合并期间进行。合并会在后台一个不确定的时间进行。有一些数据可能仍未被处理。尽管你可以调用 OPTIMIZE 语句发起计划外的合并,但请不要依靠它,因为 OPTIMIZE 语句会引发对数据的大量读写。


创建 dwd 订单 MATERIALIZED VIEW:


CREATE TABLE IF NOT EXISTS test.dwd_order (    order_code String COMMENT '订单编码',    order_amt Decimal32(2) COMMENT '订单金额',    order_status String COMMENT '订单状态',    order_date DateTime COMMENT '下单日期',    order_rec_date DateTime COMMENT '接单日期',    order_com_date DateTime COMMENT '成单日期',    shop_code String COMMENT '门店编码',    member_code String COMMENT '会员编码',    sign Int8,    version UInt8) ENGINE = ReplacingMergeTree(version) PARTITION BY shop_codeORDER BY order_codeSETTINGS index_granularity = 8192;
CREATE MATERIALIZED VIEW IF NOT EXISTS test.dwd_order_v to test.dwd_orderas select order_code, order_amt, order_status, order_date, order_rec_date, order_com_date, shop_code, member_code, sign , version from test.ods_real_time_order ;
insert into test.dwd_order select order_code, order_amt, order_status, order_date, order_rec_date, order_com_date, shop_code, member_code, sign , version from test.ods_real_time_order ;
复制代码


这里使用带有 TO [db].[table]方式创建 MATERIALIZED VIEW,不能够使用 populate 初始化视图的数据,所以这种情况下,我们需要手动加载视图创建之前的源表中的数据;因为在探索过程中发现如果 dwd 使用 without TO [db].[table] 创建 MATERIALIZED VIEW,dws 再基于这个 MATERIALIZED VIEW 创建 dws 的 MATERIALIZED VIEW,ods 写入的订单数据无法同步到 dws 的 MATERIALIZED VIEW,因此使用带有 TO [db].[table]方式创建 MATERIALIZED VIEW。


查看下 dwd 订单数据,只剩下 version 最大的订单,解决了 ods 遗留下重复订单问题


select * from test.dwd_order;
SELECT *FROM test.dwd_order
Query id: 99a7359a-ba4a-46f9-8acc-cba6be734a4f
┌─order_code─┬─order_amt─┬─order_status─┬──────────order_date─┬──────order_rec_date─┬──────order_com_date─┬─shop_code─┬─member_code─┬─sign─┬─version─┐│ o_0001 │ 10.05 │ 完成支付 │ 2022-10-01 00:00:00 │ 2022-10-01 00:00:01 │ 2022-10-01 00:00:02 │ s_0001 │ m_0001 │ 1 │ 3 │└────────────┴───────────┴──────────────┴─────────────────────┴─────────────────────┴─────────────────────┴───────────┴─────────────┴──────┴─────────
复制代码


因为 clickhosue 的 Materialized views 存在以下局限,也就是 Materialized views 视图只在 inserted data 时触发执行同步数据。


Materialized views in ClickHouse are implemented more like insert triggers. If there’s some aggregation in the view query, it’s applied only to the batch of freshly inserted data. Any changes to existing data of source table (like update, delete, drop partition, etc.) does not change the materialized view.Materialized views 的局限会导致以下问题


  • ods 订单删除,dwd 层感知不到如 ods 删除订单号为 o_0001 订单,在分别对 ods、dwd 进行 OPTIMIZE


INSERT INTO test.ods_real_time_order Values ('o_0001', 10.05,'完成支付','2022-10-01 00:00:00','2022-10-01 00:00:01','2022-10-01 00:00:02','s_0001','m_0001',-1,3);
复制代码


查看 ods、dwd 订单数据,ods 已经删除 version=3 订单,但 dwd 还存在此订单。此问题可以跟上游约定对 ods 数据物理 delete,改为逻辑 delete,如增加一条 version=4 订单,订单状态为“取消单”;或者下游使用时过滤掉 sign=-1 数据。


instance-vx60mbtu :) select * from test.ods_real_time_order;
SELECT *FROM test.ods_real_time_order
Query id: 2d470d80-34dc-4770-acdb-4b242a74a6dc
┌─order_code─┬─order_amt─┬─order_status─┬──────────order_date─┬──────order_rec_date─┬──────order_com_date─┬─shop_code─┬─member_code─┬─sign─┬─version─┐│ o_0001 │ 10.05 │ 成单 │ 2022-10-01 00:00:00 │ 2022-10-01 00:00:01 │ 1970-01-01 08:00:00 │ s_0001 │ m_0001 │ 1 │ 2 │└────────────┴───────────┴──────────────┴─────────────────────┴─────────────────────┴─────────────────────┴───────────┴─────────────┴──────┴─────────┘
1 row in set. Elapsed: 0.002 sec.
instance-vx60mbtu :) select * from test.dwd_order
SELECT *FROM test.dwd_order
Query id: 8d3940c9-9852-4ddb-860c-92b705c04571
┌─order_code─┬─order_amt─┬─order_status─┬──────────order_date─┬──────order_rec_date─┬──────order_com_date─┬─shop_code─┬─member_code─┬─sign─┬─version─┐│ o_0001 │ 10.05 │ 完成支付 │ 2022-10-01 00:00:00 │ 2022-10-01 00:00:01 │ 2022-10-01 00:00:02 │ s_0001 │ m_0001 │ -1 │ 3 │└────────────┴───────────┴──────────────┴─────────────────────┴─────────────────────┴─────────────────────┴───────────┴─────────────┴──────┴─────────┘
1 row in set. Elapsed: 0.002 sec.
复制代码

dws

在 dws 订单表首先使用 AggregatingMergeTree 引擎创建门店天汇总订单表,再使用 SummingMergeTree 引擎创建门店月汇总订单。clickhosue 的 AggregatingMergeTree 引擎真的溜溜的,之前也使用过其他 olap 引擎设计 cube,通过预计算与层层折叠提高模型复用性与查询性能,但一直没法覆盖去重场景,如统计 uv 指标时,同一天内相同的客户端只被计算一次,clickhosue 的 AggregatingMergeTree 引擎就可以很好覆盖这类场景。


AggregatingMergeTree 表来做增量数据的聚合统计,包括物化视图的数据聚合;要插入数据,需使用带有 -State- 聚合函数的 INSERT SELECT 语句。 从 AggregatingMergeTree 表中查询数据时,需使用 GROUP BY 子句并且要使用与插入时相同的聚合函数,但后缀要改为 -Merge 。


创建 dws 门店天汇总订单表,计算门店每天成单金额与成单用户数(相同的用户只被计算一次)


CREATE table IF NOT EXISTS test.dws_shop_order_daily (    order_date UInt32 COMMENT '下单日期',    shop_code String COMMENT '门店编码',    order_amt AggregateFunction(sum, Decimal32(2)) DEFAULT initializeAggregation('sumState', toDecimal32(0,2)) COMMENT '成单金额',    uv AggregateFunction(uniq, String) COMMENT '成单用户数')ENGINE = AggregatingMergeTree()PARTITION BY order_dateORDER BY (shop_code)
CREATE MATERIALIZED VIEW IF NOT EXISTS test.dws_shop_order_daily_v to test.dws_shop_order_daily as select toYYYYMMDD(a.order_date) AS order_date, a.shop_code, sumState(a.order_amt) AS order_amt, uniqState(member_code) AS uvfrom test.dwd_order a where a.order_status='成单' group by a.shop_code,toYYYYMMDD(a.order_date)
insert into test.dws_shop_order_daily select toYYYYMMDD(a.order_date) AS order_date, a.shop_code, sumState(a.order_amt) AS order_amt, uniqState(member_code) AS uvfrom test.dwd_order a where a.order_status='成单' group by a.shop_code,toYYYYMMDD(a.order_date)
复制代码


查看下 dws 门店天汇总订单数据


SELECT    order_date,    shop_code,    sumMerge(order_amt),    uniqMerge(uv)FROM test.dws_shop_order_dailyGROUP BY    shop_code,    order_date
Query id: f451a173-8a4b-49f9-8c0a-f16f8ab21845
┌─order_date─┬─shop_code─┬─sumMerge(order_amt)─┬─uniqMerge(uv)─┐│ 20221001 │ s_0001 │ 10.05 │ 1 │└────────────┴───────────┴─────────────────────┴───────────────┘
1 row in set. Elapsed: 0.003 sec.
复制代码


会员 m_002 在 2022-10-01 01:00:03 在门店 s_0001 完成订单 o_0002 支付。


INSERT INTO test.ods_real_time_order Values ('o_0002', 10.05,'完成支付','2022-10-01 01:00:00','2022-10-01 01:00:01','2022-10-01 01:00:02','s_0001','m_0002',1,3);
复制代码


再查看 dws 门店天汇总订单数据


Query id: 84b44aa5-1f3d-4b5d-bb2d-dface9b25c67
┌─order_date─┬─shop_code─┬─sumMerge(order_amt)─┬─uniqMerge(uv)─┐│ 20221001 │ s_0001 │ 20.1 │ 2 │└────────────┴───────────┴─────────────────────┴───────────────┘
复制代码


创建 dws 门店月汇总订单表,计算每月门店成单金额


合并 SummingMergeTree 表的数据片段时,ClickHouse 会把所有具有相同主键的行合并为一行,该行包含了被合并的行中具有数值数据类型的列的汇总值。列中数值类型的值会被汇总。这些列的集合在参数 columns 中被定义。如果用于汇总的所有列中的值均为 0,则该行会被删除。如果列不在主键中且无法被汇总,则会在现有的值中任选一个。主键所在的列中的值不会被汇总。


CREATE TABLE test.dws_shop_order_monthly(    order_date UInt32 COMMENT '下单年月',    shop_code String COMMENT '门店编码',    order_amt Decimal32(2) COMMENT '成单金额')ENGINE = SummingMergeTree(order_amt)PARTITION BY order_dateORDER BY (shop_code,order_date);
CREATE MATERIALIZED VIEW IF NOT EXISTS test.dws_shop_order_monthly_v to test.dws_shop_order_monthlyas with t as ( SELECT order_date, shop_code, sumMerge ( order_amt ) as order_amt, uniqMerge ( uv ) as uv FROM test.dws_shop_order_daily GROUP BY shop_code, order_date)select toYYYYMM(toDate(toString(order_date))) as order_date, shop_code, sum(order_amt) AS order_amtfrom t group by shop_code,order_date;

insert into test.dws_shop_order_monthlywith t as ( SELECT order_date, shop_code, sumMerge ( order_amt ) as order_amt, uniqMerge ( uv ) as uv FROM test.dws_shop_order_daily GROUP BY shop_code, order_date)select toYYYYMM(toDate(toString(order_date))) as order_date, shop_code, sum(order_amt) AS order_amtfrom t group by shop_code,order_date
复制代码


查看下 dws 门店月汇总订单数据


SELECT    order_date,    shop_code,    sum(order_amt)FROM test.dws_shop_order_monthlyGROUP BY    shop_code,    order_date
Query id: de50fd82-52fc-4f30-b460-50982a76ff45
┌─order_date─┬─shop_code─┬─sum(order_amt)─┐│ 202210 │ s_0001 │ 20.1 │└────────────┴───────────┴────────────────┘
1 row in set. Elapsed: 0.003 sec.
复制代码


会员 m_003 在 2022-10-02 01:00:03 在门店 s_0001 完成订单 o_0003 支付。会员 m_004 在 2022-11-01 01:00:03 在门店 s_0001 完成订单 o_0004 支付。


INSERT INTO test.ods_real_time_order Values ('o_0003', 10.05,'完成支付','2022-10-02 01:00:00','2022-10-01 01:00:01','2022-10-01 01:00:02','s_0001','m_0003',1,3),('o_0004', 10.05,'完成支付','2022-11-01 01:00:00','2022-11-01 01:00:01','2022-11-01 01:00:02','s_0001','m_0004',1,3);
复制代码


查看下 dws 门店月汇总订单数据


Query id: c25f8265-cab5-4269-9213-ff8fb82adb7e
┌─order_date─┬─shop_code─┬─sum(order_amt)─┐│ 202210 │ s_0001 │ 30.15 ││ 202211 │ s_0001 │ 10.05 │└────────────┴───────────┴────────────────┘
2 rows in set. Elapsed: 0.003 sec.
复制代码

结论

通过实践结果对 clickhouse 作为准实时数仓能力进行总结


  • 数据复用性:通过对数据分层与 clickhosue 提供的 MATERIALIZED view 能力,可以解决数据重复建设,提高数据复用性,同时简化数据处理(不用配置与维护任务调度)。

  • 分钟级数据时效性:clickhosue 提供的 MATERIALIZED view 能力可以提高数据在各层同步时效 。

  • 快速查询响应:MergeTree Engine Family 引擎通过预计算与增量计算可以提高数据处理性能。

  • 实时数据写入:使用 CollapsingMergeTree 与 VersionedCollapsingMergeTree 表引擎可以实现数据实时写入。


同时 clickhouse 存在的以下局限会因为数据分层,特别是层出引用之后问题被放大,同时增加数据开放成本(需要各种兜底方案),增加运维复杂性(问题定位复杂),在下个专题讨论这些局限解决方案。


  • merge 在不可预知情况发生

  • MATERIALIZED VIEW 的数据同步只发生在 insert

发布于: 刚刚阅读数: 5
用户头像

水滴

关注

技术无产阶级 2020.03.23 加入

弱小和无知不是生存的障碍,傲慢才是。

评论

发布
暂无评论
clickhosue准实时数仓能力探索_实时数仓_水滴_InfoQ写作社区