这是我参与「第五届青训营 」伴学笔记创作活动的第 9 天
本篇笔记主要记录一下ClickHouse的学习知识
1.列式存储的优点
- 数据压缩
-
- 数据压缩可以使读的数据量更少,在IO密集型计算中有更大性能优势
-
- 相同类型压缩效率更高
-
- 排序之后压缩效率更高
-
- 可以针对不同类型采用不同的压缩算法
- 数据选择
-
- 可以选择特定的列做计算而不是读全部列
-
- 对聚合计算友好
- 延迟物化
-
- 物化:将列数据转换为可以被计算或者输出的行数据或者内存数据结果的过程
-
- CPU/内存带宽友好
-
- 可以利用到执行计划和算子的优化
-
- 保留直接在压缩列做计算的机会
- 向量化
-
- SIMD
-
- 数据格式
-
- 执行模型
2.ClickHouse存储设计
1.表结构和定义
- 分布式表:不存储数据,用于将查询路由到集群的各个节点
-
- cluster:逻辑集群,由多个节点组成
-
- shard_key:知道数据写入分布式表时的分布方式
- 本地表:实际存储数据的表
2.集群架构
- ClickHouse节点选定方向横向分布:
- ClickHouse节点选定方式纵向分布:
3.引擎架构
- Client发起请求到Server-Handler
- Server-Handler包含可以处理TCP和Http的请求,处理后发给Parser
- Parser处理请求形成ASP树交给Interpreter
- 之后和Storages交互,Executor执行
4.存储架构
- part是物理文件夹名字
- partition是逻辑结构
- 一个part有一个主键索引
- 每个column都有列索引
3.索引设计
1.Hash Index
- 将输入的key通过hashFunc映射到一组bucket
- 每个bucket都包含一个指向一条记录的地址
- 哈希索引在查找的时候只适用于等值比较
2.B-Tree
- 数据写入是有序的,支持增删改查
- 每个节点有多个子节点
- 每个节点按升序排列key值
- 每个key有两个指向左右子节点的引用 (左小右大)
3.B+Tree
- 所有数据存储在叶节点,非叶节点只存key值
- 叶节点维护到相邻节点的引用 (双向链表)
- 可以通过key值二分查找,也可以通过叶节点顺序访问
4.LSM-Tree
- Log-structured merge-tree是一种为大吞吐写入场景而设计的数据结构
- 着重优化顺序写入
- 主要数据结构:SSTables、Memtable
- SSTables
- key按顺序存储到文件中,称为segment
- 包含多个segment
- 每个segment写入磁盘后都是不可更改的,新加的数据只能生成新的segment
- Memtable
-
在内存中的数据保存在memtable中,大多数实现都是一颗二叉搜索树
-
当memtable存储的数据到达一定的阈值的时候,就会按顺序写入到磁盘
-
数据查询:从最新的segment开始遍历每个key,也可以为每个segment建一个索引
-
合并:将多个segments合并成一个segments,一般有一个后台线程完成,不同的segments写入新的segments的时候也需要排序,形成新的之后,旧segment文件就会被删除
4.实现LSM-Tree
实现一个主键索引
- 数据按照主键顺序依次排序,先按照UserId排序、再按照URL排序、最后是EventTime
- 数据将会被划分成granules,是最小的读取单元,不同的granules可以并行读取,每个granule都对应primary.idx里面的一行,里面存储的每一行数据被称为index mark
- 每个列都有一个mark文件,mark文件保存的是每个granules的物理地址
- 缺陷:数据按照key的顺序做排序,因此只有第一个key的过滤效果好,后面的key过滤效果依赖于第一个key的基数大小
人生苦短,不如go浪一下。