Clickhouse架构与实践:Clickhouse核心特性概述

126 阅读8分钟

Clickhouse架构与实践一:Clickhouse核心特性概述

1.前言

Olap系统架构分类

OLAP(OnLine Analytical Processing),即联机分析处理。OLAP对业务数据执行多维分析,并提供复杂计算,趋势分析和复杂数据建模的能力。

从架构上可分类为

  • 第一类架构 ROLAP ( Relational OLAP ,关系型 OLAP )

它直接使用关系模型构建,数据模型常使用星型模型或者雪花模型 。 这种架构对数据的实时处理能力要求很高。 但是对于大数据场景下,多字段groupby性能表现常常显得力不从心。

  • 第二类架构 MOLAP (Multidimensional OLAP , 多维型 OLAP )

MOLAP 使用多维数组的形式保存数据,其核心思想是借助预先聚合结果,使用空间换取时间的形式最终提升查询性能 。

通过预处理的形式,对各种维度进行组合并事先聚合;最后,将聚合结果以某种索引或者缓存的形式保存起来(通常只保留聚合后的结果,不存储明细数据) 。

  • 第三类架构 HOLAP (Hybrid OLAP ,混合架构的 OLAP ) 。

这种思路可以理解成ROLAP 和 MOLAP 两者的集成 。

预聚合系统存在的问题

  1. 由于预先聚合只能支持固定的分析场景,所以它无法满足自定义分析的需求 。
  2. 维度组合爆炸会导致数据膨胀,这样会造成不必要的计算和存储开销 。 因为用户 并不一定会用到所有维度的组合,那些没有被用到的组合将会成为浪费的开销 。
  3. 流量数据是在线实时接收的,所以预聚合还需要考虑如何及时更新数据 。

Clickhouse系统概述

ClickHouse 是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。数据始终是按列存储的,包括矢量执行的过程,它有利于降低实际的数据处理开销。

1.列式存储

列式存储和数据压缩,对于一款高性能数据库来说是必不可少的特性 ,如果你想让查询变得更快,最简单且有效的方法是减少数据扫描范围和数据传输时的大小,而列式存储和数据压缩就可以帮助我们实现上述两点 。

按列存储与按行存储相比,前者可以有效减少查询时所需扫描的数据量,这一点可以 用一个示例简单说明 。 假设一张数据表 A 拥有 50 个字段 Al ~A50 ,以及 100 行数据 。 现 在需要查询前 5 个字段并进行数据分析, 则可以用如下 SQL 实现 :

SELECT Al , A2 , A3 , A4 , A5 FROM A

如果数据按行存储,数据库首先会逐行扫描,并获取每行数据的所有 50 个字段,再从每一行数据中返回 A l ~AS 这 5 个字段 。 不难发现,尽管只需要前面的 5 个字段,但由于 数据是按行进行组织的,实际上还是扫描了所有的字段 。 如果数据按列存储,就不会发生 这样的问题。 由于数据按列组织,数据库可以直接获取 A l ~AS 这 5 列的数据,从而避免 了多余的数据扫描 。

如果数据按行存储,数据库首先会逐行扫描,并获取每行数据的所有 50 个字段,再从 每一行数据中返回 A l ~AS 这 5 个字段 。 不难发现,尽管只需要前面的 5 个字段,但由于 数据是按行进行组织的,实际上还是扫描了所有的字段 。 如果数据按列存储,就不会发生 这样的问题。 由于数据按列组织,数据库可以直接获取 A l ~AS 这 5 列的数据,从而避免 了多余的数据扫描 。

2.数据压缩

按列存储相比按行存储的另一个优势是对数据压缩的友好性 。 同样可以用一个示例简单说明压缩的本质是什么 。 假设有两个字符串 abcdefghi 和 bcdefghi ,现在对它们进行压 缩,如下所示: 压缩前 : abcdefghi_bcdefghi 压缩后: abcdefghi一( 9' 8) 可以看到,压缩的本质是按照一定步长对数据进行匹配扫描,当发现重复部分的时-候 就进行编码转换 。 例如上述示例中的(9 ,的,表示如果从下划线开始向前移动 9 个字节, 会匹配到 8 个字节长度的重复项,即这里的 bcdefghi 。

3.向量化执行引擎

为了实现向量化执行,需要利用 CPU 的 SIMD 指令 。 SIMD 的全称是 Single Instruction Multiple Data ,即用单条指令操作多条数据 。 现代计算机系统概念中,它是通过数据井行以提高性能的一种实现方式(其他的还有指令级并行和线程级并行),它的原理是在 CPU 寄存器层面实现数据的并行操作 。

4.关系模型

ClickHouse 使用关系模型描述数据并提供了传统数据库的概念(数据库、表、视图和函数等) 。 与此同时, ClickHouse 完全使用 SQL 作为查询语言(支持 GROUP BY 、 ORDER BY 、 JOIN 、 IN 等大部分标准 SQL。

5.多线程与分布式

  • 多线程

如果说向量化执行是通过数据级并行的方式提升了性能,那么多线程处理就是通过线程级并行的方式实现了性能的提升 。 相比基于底层硬件实现的向量化执行 SIMD , 线程级并行通常由更高层次的软件层面控制 。

  • 分布式

ClickHouse 则采用 Multi-Master 多主架构,集群中的每个节点角色对等,客户端访问任意一个节点都能得到相同的效果 。

  • 分片

ClickHouse 并不像其他分布式系统那样,拥有高度自动化的分片功能 。 Clickouse 提供了本地表( Local Table )与分布式表( Distributed Table )的概念。一张本地表等同于一份 数据的分片。

而分布式表本身不存储任何数据,它是本地表的访问代理,其作用类似分库中间件借助分布式表,能够代理访问多个数据分片,从而实现分布式查询 。

6.Clickhouse系统架构

图2-2ClickHouse架构设计中的核心模块.png

  • Column 和 Field 是 ClickHouse 数据最基础的映射单元 。

Column 对象分为接口和实现两个部分,在 IColumn 接口对象中,定义了对数据进行各种关系运算的方法。

如果需要操作单个具体的数值(也就是单列中的一行数据), 则需要使用 Field 对象, Field 对象代表一个单值 。 与 Column 对象的泛化设计思路不同, Field 对象使用了聚合的设计模式 。 在 Field对象内部聚合了 Null 、 Ulnt64 、 String 和 Array 等 13 种数据类型及相应的处理逻辑 。

  • DataType

数据的序列化和反序列化工作由 DataType 负责 。

IDataTyp巳接口定义了许多正反序列化的方法,它们成对出现,例如 serializeB inary 和 deserializeB inary 、 serializeTextJSON 和deserializeTextJSON 等,涵盖了常用的二进制 、 文本、 JSON 、 XML 、 csv 和 Protobuf 等多种格式类型。

  • Block 与 Block 流

ClickHouse 内部的 数据操 作 是面 向 Block 对 象进行的,并且采用了流的形式 。

Block 对象的本质是由数据对象、数据类型和列名称组成的三元组,即 Column 、 DataType 及列名称字符串 。

在具体的实现过程中, Block 并没有直接聚合 C olumn 和 DataType 对象, 而是通过ColumnWithTypeAndName对象进行间接引用 。

  • Table

在数据表的底层设计中并没有所谓的 Table 对象,它直接使用 IStorage 接口指代数据表 。

在数据查询时, IStorage负责根据 AST 查询语句的指示要求,返回指定列的原始数据 。 后续对数据的进一步加工、计算和过滤,则会统一交由 Interpreter 解释器对象处理 。

  • Parser 与 Interpreter

Parser 分析器负责创建 AST 对象;而Interpreter 解释器则 负责解释 AST ,并进一 步创建查询的执行管道。

Interpreter 解释器的作用就像 Service 服务 层一样, 起到串联 整个查询过程的作用,它会根据解释器的类型,聚合它所需要的资源 。

  • Functions 与 Aggregate Functions

函数效果作用于每行数据之上 。 当然,在函数具体执行的过程中,并不会一行一行地运算,而是采用向量化的方式直接作用于一整列数据 。

普通函数由!Function 接口定义,拥有数十种函数实现 ,例如 FunctionFormatDateTime 、 unctionSubstring 等 。

聚合函数由 IAggregateFunction 接口定义,相比无状态的普通函数,聚合函数是有状态的 。聚合函数的状态支持序列化与反序列化,所以能够在分布式节点之间进行传输,以实现增量计算 。

7.Clickhouse的优势

执行速度快的原因

  1. 列式存储数据
  2. 向量化引擎
  3. 在每个细节积累性能
  4. CPU 的向量化执行 SIMD
  5. 不同状况,选择使用不同的实现算法
  6. 持续迭代

文章内容引自ClickHouse原理解析与应用实践