ClickHouse读书笔记(二)—架构概述
一、名词
MMP:Massively Parallel Processing,是将任务并行的分散到多个服务器和节点上,在每个节点上计算完成后,将各自部分的结果汇总在一起得到最终的结果。采用MPP架构的数据库称为MPP数据库。
向量化执行引擎:简单理解为就是消除程序循环的优化,堆机器加快速度。实现向量化执行,需要利用CPU的SIMD指令。
SIMD:Single Instruction Multiple Data,用单条指令操作多条数据,不适合用于带有较多分支判断的场景。
DBMS:Database Management System,数据库管理系统。
AST:Abstract syntax tree,抽象语法树。
二、ClickHouse特点
1、完备的DBMS功能
- DDL:Data Definition Language,数据定义语言,可以动态地创建、修改或删除数据库、表和视图,无须重启服务。
- DML:Data Manipulation Language,数据操作语言,可以动态增删改查数据。
- 权限控制:可以按照用户粒度设置数据库或者表的操作权限,保障数据的安全性。
- 数据备份与恢复:提供了数据备份导出与导入恢复机制,满足生产环境的要求。
- 分布式管理:提供集群模式,自助管理多个数据库节点。
2、列式存储和数据压缩
列式存储,在扫描指定列时,不用按行组织其他非指定列的数据,避免多余的数据扫描。
数据压缩,按照一定步长对数据进行匹配扫描,当发现重复部分的时候就进行编码转换,降低IO和存储的压力。例如【abcdefghi_bcdefghi】压缩成【abcdefghi_(9,8)】,如果从下划线开始向前移动9个字节,会匹配到8个字节长度的重复 项,即这里的bcdefghi。数据默认使用LZ4算法压缩。
3、向量化执行引擎
简单理解就是消除程序循环的优化,堆机器加快速度,数据级并行。实现向量化执行,需要利用CPU的SIMD指令。
4、关系模型与SQL查询
- 关系模型相比键值对等其他模型拥有更好的描述能力,在OLAP领域,已经有大量数据建模都是基于关系模型,其他数据库迁移到CK的成本很低。
- 完全使用SQL作为查询语言(支持 group by、order by、join、in等大部分标准SQL),SQL解析时大小写敏感(select a 和 select A不同)。
5、多样化的表引擎
CK的最初架构是基于MySQL实现的,表引擎设计就与MySQL类似,存储引擎作为一层独立的接口。种类繁多,根据业务场景自行选择。
6、多线程与分布式
- 多线程处理就是通过线程级并行的方式实现了性能的提升。相比基于底层硬件实现的向量化执行SIMD,线程级并行通常由更高层次的软件层面控制。多线程处理(线程级并行)与向量化执行(数据级并行)形成互补。
- 预先将数据分布到各台服务器,将数据的计算查询直接下推到数据所在的服务器,因为计算移动比数据移动更加划算。
ClickHouse在数据存取方面,既支持分区(纵向扩展,利用多线程原理),也支持分片(横向扩展,利用分布式原理),可以说是将多线程和分布式的技术应用到了极致。
7、多主架构
Multi-Master多主架构,集群中的每个节点角色对等,天然规避单点故障问题,适用于多数据中心、异地多活场景。
8、在线查询
与其他分析型数据库对比,存在许多相似之处,例如都支持海量查询场景、支持列式存储、数据分片、计算下推等特效,说明CK在设计上吸取了各路优点。
价格方面:其他开源系统慢,商用系统贵。CK又快又免费。
9、数据分片和分布式查询
- CK有本地表(Local Table)和分布式表(Distributed Table),一张本地表等同于一份数据的分片,而分布式表不存储数据,只是本地表的访问代理。
- 分布式表类似分库中间件,代理访问多个数据分片,实现分布式查询。
三、架构设计
1、Column与Field
这两个是CK最基础的映射单元,一列数据用一个Column对象表现,一列中的某一行(具体数值)用Field对象表示。
2、DataType
负责数据的序列化和反序列化相关工作,但是并不直接负责数据的读取,而是转由Column或Field对象获取。在DataType的实现类中,聚合了相应数据类型的Column对象和Field对象。例如DataTypeString会引用字符串类型的ColumnString,而DataTypeArray则会引用数组类型ColumnArray,以此类推。
3、Block与Block流
CK的数据操作是面向Block对象进行的,并且是采用流的形式。虽然Column与Field组成了数据的基本映射单元,但对应到实际操作,它们还缺少一些必要信息,例如数据的类型以及列的名称。于是乎,设计出了Block对象,Block=数据对象(Column/Feild) + DataType + 列名称字符串。
流操作有两个顶层接口:IBlockInputStream负责数据的读取和关系运算,IBlockOutputStream负责将数据输出到下一环节。
4、Table
在数据表的底层设计中并没有所谓的Table对象,它直接使用 IStorage接口指代数据表。
表引擎是ClickHouse的一个显著特性, 不同的表引擎由不同的子类实现,例如IStorageSystemOneBlock (系统表)、StorageMergeTree(合并树表引擎)和 StorageTinyLog(日志表引擎)等。
5、Parser和Interpreter
Parser分析器负责创建AST对象,而Interpreter解释器则负责解释AST,并进一步创建查询的执行管道。它们与IStorage一起,串联起了整个数据查询的过程。Parser分析器可以将一条SQL语句以递归下降的方法解析成 AST语法树的形式。不同的SQL语句,会经由不同的Parser实现类解析。
6、Functions与Aggregate Functions
普通函数,例如四则运算、日前转换、网址提取函数、IP地址脱敏函数。没有状态,函数效果作用于每行数据之上。在函数具体执行过程中,采用向量化的方式直接作用于一整列数据,而不是一行一行计算。
聚合函数,有状态的,例如COUNT聚合函数,AggregateFunctionCount的状态用整型UInt64记录。聚合函数 的状态支持序列化与反序列化,所以能够在分布式节点之间进行传 输,以实现增量计算。
7、Cluster与Replication
集群由分片(Shard)组成,分片由副本(Replica)组成。
CK的1个节点只能拥有一个分片,如果要实现1分片、1副本,至少需要部署两个服务节点。
分片是逻辑概念,物理承载由副本承担。
四、CK为什么这么快?
- CK的设计采用自下而上的方式,因为最初的目的只是以最快速度进行group by 查询和过滤。
- 针对特定场景,采用不同的底层算法。
- 在各个方面持续测试,持续改进。