ClickHouse|青训营笔记

28 阅读4分钟

这是我参与「第五届青训营 」笔记创作活动的第15天

数据库基本概念

按照一定的格式有序集合 可以通过查询语言获取想要的信息(SQL,API,直接访问等方式)

数据库类型

  • 关系型数据库:数据以表的形式存储,表之间建立关系

  • 非关系型数据库:NoSQL或者非关系型数据库。数据之间是独立的

  • 单机数据库:在一个节点上存储

  • 分布式数据库:由不同站点的两个或多个文件组成,可以存储在多台物理机上。

  • OLTP:(Online transactional processing)数据库是一种高速分析数据库,专为多个用户执行大量事务而设计

  • OLAP:Online analytical processing数据库旨在同时分析多个数据维度,帮助用户更好的理解数据中的复杂关系

    • 大量数据的读写,PB级别的存储

    • 多为分析,复杂的聚合函数

    • 窗口函数,自定义User Define Function

    • 离线/实时分析

image.png

列式存储

列式存储是将众多数据的同一列数据按照顺序存储

image.png

优点

数据压缩

- 数据压缩可以使读的数据量更少,在IO密集型计算中获得更大的性能优势
- 相同类型压缩效率更高
- 排序之后压缩效率更高
- 可以针对不同类型使用不同的压缩算法

例子:

image.png LZ4

  • (5,4)代表向前5个byte,匹配到长度为4,即“bcde”是重复
  • 重复项越多,压缩率越高

image.png

Run-length endoding

  • 压缩重复的数据
  • 可以在压缩数据上直接计算,比如统计有多少个重复w的值

image.png Delta Encoding

  • 将数据存储为连续数据之间的差异,而不是存储数据本身
  • 特定算子也能直接在压缩数据上计算,比如计算数据的总和等

数据选择

  • 可以选择特定的列作计算而不是读所有列
  • 对聚合计算友好,而不是遍历所有的行去取出对应的列进行拼接

延迟物化

物化:将列数据转化为可以被计算或者输出的行数据或者内存数据结果的过程。物化后的数据通常可以用来做数据过滤,聚合计算,join等

  • 缓存友好
  • CPU/内存宽带友好
  • 可以利用到执行计划和算子的优化,例如filter
  • 保留直接在压缩列做计算的机会

向量化

  • SIMD(single instruction multiple data),现代多核CPU,实现一条指令执行多条数据。

image.png 寄存器宽度越宽,处理的数据量可以越大。例如for循环可以直接拼接进行向量化计算,而不是循环多次

  • 数据格式
    • 需要处理多个数据,因此数据需要是连续内存
    • 需要明确的数据类型
  • 执行模型要求:
    • 数据需要按批读取
    • 函数的调用需要明确的数据类型

优缺点总结

image.png

存储设计

表定义和结构

  • 分布式表:不存储数据,用于将请求路由到集群的各个节点
    • cluster:逻辑集群,由多个节点组成
    • shard_key:指导数据写入分布式表时的分布式
  • 本地表:实际存储数据的表

image.png

集群架构

distributed——table用于将请求路由到对应的shard,选择查哪个副本

image.png

引擎架构

image.png

  • part是物理文件夹的名字
  • artition是逻辑结构
  • part和column
    • 每个column都是一个文件
    • 所有的column文件都在自己的part文件夹下
  • column和index
    • 一个part有一个逐渐索引
    • 每个column都有列索引

索引设计

  • Hash index 不适合大范围的聚合的查询
  • B-tree 数据写入是有序的,支持增删改查。每个节点有多个孩子
  • B+tree 所有的数据都存储在叶子节点,叶子节点是一个双向列表的结构

存在问题

  • 对于大数据量,B(B+)-tree深度太高
  • 索引数据量,多个列如何平衡查询和存储
  • OLAP场景写入量非常大,如何优化写入

LSM-Tree(Log-structured merge-tree)是一种为大吞吐写入场景而设计的数据结构

  • 着重优化顺序写入
  • 主要数据结构
    • SSTables
      • Key按顺序存储到文件中,称为segment
      • 包含多个segment
      • 每个segment写入磁盘后都是不可更改的,新加的数据只能生成新的segment
    • Memtable
      • 在内存中的数据保存在memtable中,大多数实现都是一个binary search tree
      • 当memtable存储的数据达到一定的阈值时,就会按照顺序写入到磁盘

数据查询

  • 需要从最新的segment开始遍历每个key
  • 也可以为每个segment建立一个索引

compaction(合并)

  • 将多个segment合并为一个segment
  • 一般由一个后台线程完成
  • 不同的segments写入新的segment需要排序,形成新的segment后,旧的segment文件会被删除