ClickHouse
开源列式数据库,针对 OLAP 领域
es 是搜索引擎,主要用于搜索,附带聚合能力
ck 是数据库,主要是crud,聚合查询是强项。数据库一般不具备模糊搜索的能力,或者说模糊搜索能力相对较差
1. OLAP 场景的特点
- 读多于写
OLTP 事务处理,比如购物车、下单、支付等需要在原地进行大量增删改
OLAP 分析处理,通常是批量导入数据后,进行任意维度的读
- 大宽表,读大量行但是少量列,结果集较小
OLAP 场景下,通常有多张大宽表,列数非常多,通常会扫描大量行数据,只用到其中的某几列
- 数据批量写入,且数据不更新或少更新
OLTP类业务对于延时(Latency)要求更高,要避免让客户等待造成业务损失;而OLAP类业务,由于数据量非常大,通常更加关注写入吞吐(Throughput),要求海量数据能够尽快导入完成。一旦导入完成,历史数据往往作为存档,不会再做更新、删除操作。
- 无需事务,数据一致性要求低
OLAP类业务对于事务需求较少,通常是导入历史日志数据,或搭配一款事务型数据库并实时从事务型数据库中进行数据同步。多数OLAP系统都支持最终一致性。
- 灵活多变,不适合预先建模
分析场景下,随着业务变化要及时调整分析维度、挖掘方法,以尽快发现数据价值、更新业务指标。而数据仓库中通常存储着海量的历史数据,调整代价十分高昂。预先建模技术虽然可以在特定场景中加速计算,但是无法满足业务灵活多变的发展需求,维护成本过高。
2. ClickHouse 存储层
列式存储
数据有序存储
在建表时,指定将数据按照某些列进行排序。排序后保证了数据在磁盘上连续存储,有序摆放。在进行等值、范围查找时,where命中的数据会在邻近的block中,减少了io。
进来一批数据就要重新来一次排序,所以数据进来不更新或少更新
主键索引
类似于hbase按照rowkey来划分range,每一个range的第一行作为mark,查询的时候可以根据mark行的值来快速过滤
稀疏索引
???
数据分片
集群模式可以把数据分散存储在不同的节点。比如有随机分片、固定分片、按某一列进行hash分片等等
数据分区
可以将数据根据业务随意分区,这样在查询的时候可以只过滤出需要的数据加快查询,另外可以针对特殊分区来单独进行TTL管理,淘汰过期的分区数据
数据TTl
提供行级别、列级别、分区级别的TTL,其中列级别的TTL会在一列中部分数据过期后,被替换成默认值,当一列所有数据都过期后,删除整列
高吞吐写入能力
采用LSM Tree方式
有限支持 delete、update
在 OLAP 分析场景中,删除、更新并不是核心需求,所以并没有直接提供 delete、update 等操作,而是变相支持 mutation 操作,限制了删除、更新为异步操作,只有当后台合并之后才能生效
主备同步
3. ClickHouse 计算层
多核并行
数据分片,也就是分区,每一个分区的数据再按行键分成好几个组,这样可以并行处理多组数据
分布式计算
自动把查询拆解到多个task下发到集群中,然后进行多机并行处理,最后把结果汇聚到一起。
向量化执行与SIMD
按列存储,按列计算,每一列的每一个batch调用一次SMID指令(而非每一行调用一次),不禁减少函数调用次数,提高了cpu在读取数据时缓存命中率(如果内存中按列存储,但是计算按行处理,无法充分利用cpu cache的预读能力,造成cpu cache miss严重),提高SMID指令的并行执行能力,大幅缩短计算耗时。
动态代码生成 Runtime Codegen
实现基于 Expression 级别的动态代码生成,消除了大量虚函数的调用,由于运行时表达式的参数类型、个数都是已知的,消除了不必要的if-else分支判断
近似计算
以损失一定结果精度为代价,极大地提升查询性能。
- 近似估算distinct values、中位数,分位数等多种聚合函数;
- 建表DDL支持SAMPLE BY子句,支持对于数据进行抽样处理;
- 复杂数据类型支持