大白话clickhouse原理

问题

  • clickhouse 如何高效读写数据

    • 列式存储
    • 顺序写
    • 稀疏索引
    • SIMD(single instruction multiple data)
    • MergeTree
    • 物化视图
  • clickhouse 如何实现可伸缩高可用

    • 集群分片副本
    • 分布式表
    • 存算分离

数据读写

以衣柜为持久化存储设备(磁盘),床为临时存储(内存),目录为索引,衣服为数据(裤子T恤等为数据的字段)为例,浅显说明具体的组织原理。

列式存储

含义

行式存储:衣柜每个格子都按一套衣服一套衣服来存

列式存储:衣柜的不同格子存不同衣服,A格子存T恤,B格子存裤子,C格子存袜子等

优势

统计有多少条裤子的时候,只要打开存裤子的格子即可,快速统计出来。比行式效率高。

劣势

获取一整套衣服时,需要打开多个格子组合。

顺序写

写数据,任务是要将衣服叠好排序放进衣柜。而每次来的衣服都是一套一套的,如果我们每次采购好衣服都亲自去分类叠好放进不同的衣柜再回去继续采购,将严重阻碍我们采购新的衣服的速度。为了能尽快的采购更多的衣服,我们把采购好衣服直接丢到床上,然后雇一个人小a帮我们定时将床上衣服分类排序好放进衣柜。这就是顺序写。

如果采购速度太快,我们雇的那个人可能会忙不过来。于是我们雇多个人小b,小b将小a每次分类排序好的几沓衣服再分类排序一遍,然后放进衣柜。如果采购速度仍然太快,小b也忙不过来,我们就再继续雇人。这就是lsm tree。

有利有弊,这种方式存在问题是:读放大,写放大与空间放大,即:

  • 原本只要存一次衣服,现在要存好几次;
  • 原本只要在一个地方找数据,现在要找好几个地方找;
  • 原本只用一个衣柜存,现在需要更多临时地方存。

在 HDD 作为主流存储的时代,RocksDB 的 compaction 带来的写放大问题并没有非常明显。这是因为: \1. HDD 顺序读写性能远远优于随机读写性能,足以抵消写放大带来的开销。 \2. HDD 的写入量基本不影响其使用寿命。

现在 SSD 逐渐成为主流存储,compaction 带来的写放大问题显得越来越严重:

\1. SSD 顺序读写性能比随机读写性能好一些,但是差距并没有 HDD 那么大。所以,顺序写相比随机写带来的好处,能不能抵消写放大带来的开销,这是个问题。 \2. SSD 的使用寿命和其写入量有关,写放大太严重会大大缩短 SSD 的使用寿命。因为 SSD 不支持覆盖写,必须先擦除(erase)再写入。而每个 SSD block(block 是 SSD 擦除操作的基本单位) 的平均擦除次数是有限的。

稀疏索引

有了衣柜的衣服,我们需要一个目录(索引)来帮我们快速找到想要的衣服(数据)。

当A、B、C格子存裤子时,如何快速找出想要的裤子。分两步:

    • 排序
    • 加索引

按一定规则排序,比如长度,A到C分别由短到长。其次加索引即在目录上标记中等长度裤子在B格子,那么就知道A为短裤,C为长裤。此时,想找长裤就可以不用把格子都打开,只需要打开C格子。

但如果想找的是长的蓝色裤子呢?同样的道理,对颜色也进行排序跟加索引。

将C格子分别按颜色波长进行排序,即目录上标记第一部分【红、橙】、第二部分【黄、绿、蓝】、第三部分【靛、紫】。此时我们要根据目录(索引),即知道,蓝色的长裤子在C格子的第二部分。

这就是稀疏索引。

SIMD

一条指令操作多条数据。

img

我们想要拿出所有长的T恤并且进行熨烫,一共有16件。如果我们一件一件熨烫的话,耗时会太久。这时我们可以用一个大的熨烫机,一次性熨烫四件,我们的速度会提升很多。

Intel的SSE指令集即可帮助我们实现这种对提升列式数据计算效率友好的逻辑。