ClickHouse | 青训营笔记

125 阅读8分钟

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

前言

本文主要讲解了ClickHouse的存储设计和应用场景,并复习了一些关于数据库和列式存储的基本概念,让我们更加明白ClickHouse的原理和应用。本文主要是对知识的复习和巩固,具体实践需要大家认真应用一下。

1.数据库

此处进行简单的复习,详细的知识之前文章已经进行讲述。

1.数据库概念

数据库是结构化信息或数据的有序集合,通常由数据库管理系统(DBMS)来控制。 在现实中,数据、DBMS及关联应用一起被称为数据库系统,通常简称为数据库。

简单来说,数据解析整理成有序集合,通过查询语言获得想要的信息。

2.数据库类型

  • 关系数据库:数据以形式储存
  • 非关系数据库:没有固定的表结构
  • 单机数据库:一台计算机完成数据的存储和查询
  • 分布式数据库:不同站点的多个文件存储
  • OLTP数据库:高速分析数据库,专为多个用户执行大量事务
  • OLAP数据库:同时分析多个数据维度,便于理解数据中的复杂关系

这里主要讲解OLAP数据库

image.png

  • 特点:
    • 大量数据读写,PB级存储
    • 多维分析,复杂聚合函数
    • 窗口函数,自定义UDF
    • 离线/实时分析

3.SQL

编程语言,查询、操作和定义数据,进行数据访问控制 image.png

  • SELECT:查询字段

  • FROM:指定选择的数据表

  • WHERE:限制返回行

  • GROUP BY;有相同值的行合并

  • 优点:

    • 标准化,ISO和ANSI
    • 高度非过程化,用户只用提出做什么,大大减轻了用户负担,有利于提高数据独立性
    • 以同一种语法结构提供两种使用方式(用户和程序员)
    • 语言简洁,易学易用
  • 架构如下: image.png

    • Parser:词法分析,语法分析,生成AST树
    • Analyzer:变量绑定,类型推导,语义检查等,为生成计划做准备
    • Optimizer:为查询生成性能最优的执行计划,进行代价评估
    • Executor:将执行计划翻译成可执行的物理计划并驱动其执行

4.存储引擎

  • 管理内存数据结构(索引、内存数据、缓存)
  • 管理磁盘数据(文件格式、增删查改)
  • 读写算子(写入逻辑、读取逻辑)

2.列式存储

1.优点

  • 数据压缩
  • 数据选择
  • 延迟物化
  • 向量化

2.数据压缩

  • 读的数据少,性能更好
  • 相同类型压缩效率高
  • 排序后压缩效率高
  • 针对不同类型用不同压缩算法
    • LZ4:重复项越多或越长,压缩率越高,如:abc_(5,4)
    • Run-length:压缩重复数据,压缩后的数据可直接计算,如:12w
    • Delta encoding:将数据存储为连续数据间的差异,特定算子可直接在压缩数据上计算,如:190(base),30,-20

3.数据选择

  • 可选择特定列计算而不是读所有列
  • 对聚合计算友好

4.延迟物化

  • 物化:将列数据转化为可被计算或输出的行数据或内存数据结构的过程,物化后的数据可用来做数据过滤聚合计算
  • 延迟物化:尽可能推迟物化操作发生
  • 优点
    • 缓存友好
    • CPU/内存宽带友好
    • 可利用到执行计划和算子的优化
    • 保留直接在压缩列做计算的机会

5.向量化

用SIMD指令完成的代码设计和执行逻辑

  • SIMD:用一套指令执行多条数据,指令集SSE和AVX
  • 数据格式:处理多个数据,需要连续内存;明确数据类型
  • 执行模型:数据要按批读取;明确数据类型

PS;行存VS列存 image.png

3.ClickHouse存储

1.表

  • 分布式表:不存储数据,将查询路由到集群的各个节点
    • cluster:逻辑集群,由多个节点组成
    • Shard_key:指导数据写入分布式表时的分布方式image.png
  • 本地表:实际存储数据表

2.集群架构

  • 每个shard都有备份Replica image.png

3.引擎架构

  • 和SQL的架构很像 image.png

4.存储架构

文件组织 image.png part&partition

  • part是物理文件名
  • partition是逻辑结构 image.png

part&column

  • 每个column都是一个文件
  • 所有column文件都在自己的part文件下

column&index

  • 一个part有一个主键索引
  • 每个column都有列索引

5.索引设计

  • Hash Index

    • 将输入的key通过一个HashFunction映射到一组bucket上
    • 每个bucket都包含一个指向一条记录的地址
    • 哈希索引在查找时只适用等值比较 image.png
  • B-Tree

    • 数据写入有序,支持增删查改
    • 每个节点有多个孩子节点
    • 每个节点都按照升序排列key值
    • 每个key有两个指向左右孩子节点的引用(左孩子节点保存的key都小于当前key;右孩子节点的保存的key都大于当前key) image.png
  • B+Tree

    • 所有的数据都存储在叶子节点,非叶子节点只保存key值
    • 叶子节点维护到相邻叶子节点的引用
    • 可以通过key值做二分查找,也可以通过叶子节点做顺序访问 image.png

LSM-Tree

  • 背景

    • 对于大数据量,B(B+)-Tree深度太高
    • 索引数据量太大,多个列需要平衡查询和存储
    • OLAP场景写入量非常大,需要优化写入
  • 定义:一种为大吞吐写入场景而设计的数据结构,优化顺序写入

  • 主要数据结构:SSTablesMemtable

  • SSTables:Key按顺序存储到文件中,称为segment;包含多个segment;每个segment写入磁盘后都是不可更改的,新加的数据只能生成新的segment image.png

  • Memtable:存储数据到达一定的阈值时,会按顺序写入磁盘

  • 数据查询:从最新segment遍历每个key;也可以为每个segment建一个索引

  • 合并:多个segments合并为一个segment的过程;后台线程完成;新的segment完成后旧的segment被删除

6.索引实现

步骤

  • 主键索引:先按照UserID排序,再按照URD排序,最后是EventTime image.png
  • 数据划分为granules;其为最小的数据读取单元;不同的granules可并行读取 image.png
  • 每个granule都对应primary.idx里面的一行 image.png
  • 默认每8192行记录主键的一行值, primary.idx需要被全部加载到内存里面,其里每一行数据称为一个index mark
  • 每个列都有一个mark文件,其保存的是每个granules的物理地址 image.png
  • mark文件每一行保存两个地址:block_offset(定位granule的压缩数据在物理文件中的位置)granule offset(定位一个granule在解压之后的block中的位置)

缺陷

  • 数据按照key的顺序做排序,因此只有第一个key的过滤效果好,后面的key过滤效果依赖第一个key的基数大小

7.查询优化

  • secondary index:在URL列上构建二级索引
  • 构建多个主键索引再建一个表,用需要优化的字段作为主键第一位(数据同步两份);建一个物化视图(数据自动同步到隐式表);用Projection(数据以列文件存在,数据自动同步到隐式表,查询自动路由最优的表)
  • 小结
    • 主键包含的数据顺序写入
    • 主键构造一个主键索引
    • 每个列构建一个稀疏索引
    • 通过mark的选择让主键索引可以定位到每一列的索引
    • 可以通过多种手段优化非主键列的索引

8.数据合并

多个part合并成一起的过程

  • 数据的可见性:过程中,未被合并的数据对查询可见;过程后,新part可见,旧被删除
  • 步骤
    • 通过主键找到需要读的mark
    • 切分marks,并发调度reader image.png
    • Reader通过mark block_offset得到需要读的数据文件的偏移量
    • Reader通过mark granule_offset得到解压后的数据文件的偏移量
    • 构建列式filter做数据过滤

4.ClickHouse应用场景

1.大宽表存储和查询

  • 大宽表查询

    • 建很多列,每列数据可以很方便进行更改
    • 可将列涉及到过滤条件下推到存储层从而加速查询
  • 动态表结构

    • map中的每个key都是一列
    • map中的每一列都可以单独的查询
    • 使用方式同普通列,可以做任何计算

2.离线数据分析

  • 数据导入
    • 数据可以通过spark生成clickhouse格式的文件
    • 导入到hdfs上由hive2ch导入工具完成
    • 数据导入数据直接导入到各个物理节点 image.png
  • 数据按列导入
    • 保证查询可以及时访问已有数据
    • 可按需加载需要的列

3.实时数据分析

image.png

4.memory table

  • 可以减少parts数量
  • 数据先缓存在内存中
  • 到达一定阈值再写到磁盘 image.png

5.复杂类型查询

  • bitmap索引 image.png 查询 image.png
  • bitmap64类型 image.png
  • lowcardinality
    • 对于低基数列使用字典编码
    • 减少数据存储和读写的IO使用
    • 可以做运行时的压缩数据过滤 总结
  • ClickHouse是标准的列存结构
  • 存储设计是LSM-Tree架构
  • 使用稀疏索引加速查询
  • 每个列都有丰富的压缩算法索引结构
  • 基于列存设计的高效的数据处理逻辑

小结

本文主要讲述了ClickHouse整体架构,具体的实践大家还是需要下来搜集资料的

参考

  • 字节跳动ClickHouse教程