Doris 与 Clickhouse 对比(一)

1. 常用引擎

☕️ Doris 表数据模型

  1. duplicate key

🎬 **场景:**适用于数据无需提前聚合的分析业务。

⚠️ **注意点:**只指定排序列,相同的行并不会合并。

  1. unique key

🎬 **场景:**适用于有更新需求的业务。

⚠️ **注意点:**key相同时,新记录覆盖旧记录。

  1. aggregate key

🎬 **场景:**可以提前聚合数据,适合报表和多维度业务。

⚠️ 注意点:

将会进行聚合操作,目前支持sum,min,max,replace 等

(1)sum:求和,多行的 value 进行累加。

(2)replace:替代,下一批数据中的 value 会替换之前导入过的行中的 value。

(3)max:保留最大值。

(4)min:保留最小值。

欢迎关注,一起学习

☕️ Clickhouse 表引擎

  1. *MergeTree

🎬 场景:

(1)支持索引和分区。

(2)支持生命周期TTL(列级 和表级)。

⚠️ 注意点:

(1)主键并不唯一,会建索引。

(2)order by 是必须的,主键、分区非必须。

  1. ReplacingMergeTree

🎬 **场景:**去重功能。

⚠️ 注意点:

(1)数据的去重只会在合并的过程中出现。合并会在未知的时间在后台进行,所以你无法预先作出计划。有一些数据可能仍未被处理。

(2)如果表经过了分区,去重只会在分区内部进行去重,不能执行跨分区的去重。

(3)认定重复的数据保留,版本字段值最大的如果版本字段相同则按插入顺序保留最后一次。

  1. SummingMergeTree

🎬 **场景:**对于不查询明细,只关心以维度进行汇总聚合结果的场景。

⚠️ 注意点:

(1)以 order by 的列为准,作为维度列,其他的列按插入顺序保留第一行。

(2)不在一个分区的数据不会被聚合。

2. Join 方式

  • 查询速度和并发能力,单表性能ClickHouse更好。
  • 多表Join Doris优势更明显,特别是复杂Join和大表Join大表的场景。

首先了解下向量化引擎:核心思想就是一次处理一批数据,从而大大提高数据计算的速度,例如对于一列数据,我们通过向量化技术可以一次处理1000行数据,一次将这1000行数据做比较或者做加减运算,这种处理方式在列存数据库上尤其有效,因为列存数据库通常一列一列的将数据读取处理,在内存中都是以Array的形式存储,这种方式更容易使用向量化方式做计算。

☕️ Doris Join方式

  1. Broadcast Join

🎬 **说明:**默认Join,将小表加载到内存中,形成一张Hash内存表,然后将Hash表广播到大表所在的各个节点。

⚠️ 注意点:

如果小表数据过大,Doris将自动转换为Shuffle join。

  1. Shuffle Join

🎬 **说明:**小表数据无法放入内存则进行shuffle join。

⚠️ 注意点:

每个数据扫描节点将数据扫出来之后进行Partition 分区,然后根据 Partition 分区的结果分别把左右表的数据发送到对应的 Join 计算节点上。

  1. Bucket Shuffle Join

🎬 说明:

利用建表时候分桶的特性,当join的时候,join的条件和左表的分桶字段一样的时候,将右表按照左表分桶的规则进行shuffle操作,使右表中需要join的数据落在左表中需要join数据的BE节点上的join。

⚠️ 注意点:

(1)Join 条件为等值的场景才有效。

(2)需要左表的分桶列的类型与右表等值 join 列的类型需要保持一致。

(3)只作用于 Doris 原生的表,其他表比如,ES,MYSQL无效。

  1. Colocation Join

🎬 说明:

是将一组拥有相同 CGS 的 Table 组成一个 CG。保证这些 Table 对应的数据分片会落在同一个 BE 节点上。使得当 CG 内的表进行分桶列上的 Join 操作时,可以通过直接进行本地数据 Join。

两个概念:

(1)Colocation Group(CG):位置协同组。

(2)Colocation Group Schema (CGS): CG 中的 Table的元数据信息,比如:分桶列类型,分桶数以及分区的副本数等等信息。

⚠️ 注意点:

(1)建表时两张表的分桶列的类型和数量需要一致,保证多张表的数据分片能够一一对应分布控制。

(2)同一个 CG 内所有表的所有分区的副本数必须一致。如果不一致,可能出现某一个tablet 的某一个副本,在同一个 BE 上没有其他对应的表分片的副本。

(3)同一个 CG 内的表,分区的个数、范围以及分区列的类型不要求一致。

☕️ Clickhouse Join方式

  1. 普通 Join

🎬 **步骤:**假设集群有4个节点,2个分区,2个副本,其中data1、data2 节点为一个分片 shard1,data3、data4 为一个分片 shard2。执行的SQL语句如下:

复制代码
SELECT l_.a, r_.aFROM left_all as l JOIN right_all as r 
on l_.a = r_.a

(1)Client发送data1节点上面的sql,准备执行

(2)data1节点会把自己本机表分片shard1数据left_local准备好,也即下面sql

当然,同理,data3也会把自己的left_local数据准备好

复制代码
SELECT l_.a, r_.a FROM left_local as l JOIN right_all as r 
on l_.a = r_.a

(3)当data1与data3 要开始执行第二步中 join的右表,也是一个分布式表。这个时候,data1需要shard2中的右边表数据到本地,同理data3需要shard1中的右边数据到本地。这样这两个节点都有一份全量的right_all_local。

(4)节点data1,data3 left_local数据与right_all_local做计算。

复制代码
SELECT l_.a, r_.a FROM left_local as l JOIN right_all_local as r 
on l_.a = r_.a

(5)data3执行完成以后,把结果发送到data1。

(6)data1收到数据,然后和自己计算数据做汇总,最后把结果给Client。

  1. Global Join

🎬 步骤:

还与普通Join不同的是,比如:

(1)data3节点将右表数据查询出来在data1上汇总为right_all_local。

(2)然后data1把right_all_local发送到data3上执行。

(3)data3的本地left_local数据与right_all_local计算好,发送到data1。

(4)data1收到数据,然后和自己计算数据做汇总,最后把结果给Client。

⚠️ 注意点:

(1)如果分片数为n,Global Join 右表本地表查询次数为n,而普通 Join 右表查询次数为n*n。这样可以减少读数据次数。

(2)数据在节点之间传播,占用部分网络流量。如果数据量较大,同样会带来性能损失。

3. 数据划分

☕️ Doris 数据划分

🎬 基本组成:

(1)Row & Column:一张表包括行(Row)和列(Column)。

(2)Tablet:Doris 的存储引擎中,用户数据被水平划分为若干个数据分片(Tablet,也称作数据分桶Bucket)。每个 Tablet 包含若干数据行。各个 Tablet 之间的数据没有交集,并且在物理上是独立存储的。

(3)Partition:多个 Tablet 在逻辑上归属于不同的分区(Partition)。一个 Tablet 只属于一个 Partition。而一个 Partition 包含若干个 Tablet。

🎬 数据划分:

Doris 支持两层的数据划分。第一层是 Partition,支持 Range 和 List 的划分方式。第二层是 Bucket(Tablet),支持 Hash 和 Random 的划分方式。

⚠️ 官方给出的注意点:

(1)一个表的 Tablet 总数量等于 (Partition num * Bucket num),在不考虑扩容的情况下,推荐略多于整个集群的磁盘数量。

(2)单个 Tablet 的数据量建议在 1G - 10G 的范围内。

(3)一个 Partition 的 Bucket 数量一旦指定,不可更改。所以在确定 Bucket 数量时,需要预先考虑集群扩容的情况。比如当前只有 3 台 host,每台 host 有 1 块盘。如果 Bucket 的数量只设置为 3 或更小,那么后期即使再增加机器,也不能提高并发度。

(4)官方举一些例子:假设在有10台BE,每台BE一块磁盘的情况下。如果一个表总大小为 500MB,则可以考虑4-8个分片。5GB:8-16个分片。50GB:32个分片。500GB:建议分区,每个分区大小在 50GB 左右,每个分区16-32个分片。5TB:建议分区,每个分区大小在 50GB 左右,每个分区16-32个分片。

☕️ Clickhouse 数据划分

🎬 数据分片

分片策略:

(1)random随机分片:写入数据会被随机分发到分布式集群中的某个节点上。

(2) constant固定分片:写入数据会被分发到固定一个节点上。

(3) column value分片:按照某一列的值进行hash分片。

(4) 自定义表达式分片:根据表达式的值进行hash分片。

🎬 数据分区

分区设计:

(1)不指定分区键,则数据默认不分区,所有数据写到一个默认分区a里面。

(2)如果分区键取值属于整型,则直接按照该整型的字符形式输出作为分区ID的取值。

(3)如果分区键取值属于日期类型,或者是能够转换为YYYYMMDD日期格式的整型,则按照分区表达式逻辑格式化后作为分区ID的取值。

(4)如果分区键取值既不属于整型或日期类型,则通过128位Hash算法取其Hash值作为分区ID的取值。

(5)分区键也可以是表达式的tuple元组。

相关推荐
不恋水的雨11 小时前
docker安装clickhouse数据库容器
clickhouse·docker·容器
麦兜和小可的舅舅11 小时前
ClickHouse Dist表的Replica选择逻辑深度解析-- Custom Key以及Sample的执行逻辑
c++·clickhouse·distribute·shard
布吉岛的石头11 小时前
ClickHouse性能优化:OLAP数据库实战,让查询飞起来
数据库·clickhouse·性能优化
=蜗牛=5 天前
Docker 简单部署 ClickHouse 超详细图文步骤
clickhouse·docker·容器·部署·图文
狼与自由6 天前
clickhouse log引擎
clickhouse
狼与自由7 天前
clickhouse AggregatingMergeTree
clickhouse
狼与自由8 天前
clickhouse ReplacingMergeTree
android·clickhouse
狼与自由8 天前
clickhouse中的分区
clickhouse
狼与自由8 天前
clickhouse 查询
clickhouse
狼与自由9 天前
clickhouse mergeTree
clickhouse