ClickHouse 入门:数据查询流程解析

赵先生 2024-11-06 浏览次数:0

前言

ClickHouse 是一款 ROLAP 列式数据库,在海量数据分析场景中,能够帮助我们快速得到想要的"分析性"数据。本文主要从个人视角讲解 ClickHouse 一次数据查询的整体流程,更多的是自己的一些理解和思考,如有不对,欢迎指出和交流。

ClickHouse 入门:数据查询流程解析

一、ClickHouse 数据组织形式

1.1 ClickHouse 集群、分片、副本含义

一个 ClickHouse 集群是通过分片组成。ClickHouse 分片可以由一台或者多台机器构成,当多台机器组成一个分片时,其中一个节点为主副本节点,其余则为数据副本节点,比如上图,副本数则为 1。一个 ClickHouse 集群可以由多台机器构成,当然也可以根据不同业务特性进行划分,多个集群,但每个集群都有少量机器。

ClickHouse 分片你可以理解为就是 ClickHouse 一个单机数据库实例(副本节点也算),多个这种单机数据库实例构成一个 ClickHouse 集群。分片是指包含数据不同部分的服务器(要读取所有数据,必须访问所有分片)。ClickHouse 通过分片,将一张表的数据水平分割在不同的节点上,随着业务的发展,当表数据的大小增加到很大时,也能够通过水平扩容, 保证数据的存储。

副本则是存储复制数据的服务器(要读取所有数据,访问任一副本上的数据即可)。ClickHouse 通过副本节点进行存储,用空间来换取,当主副本节点不可用时,能够选择其他副本节点进行数据服务。

1.2 MergeTree 表数据组织形式

MergeTree 表引擎数据组织形式从单个分片视角来看,底层通过目录 + 文件的方式进行组织。首先,ClickHouse 会有数据根目录,假设数据根目录为:

现在用户创建了一个数据库为 lake 的数据库,那么在这个根目录创建一个为 的目录:

当有多个数据库时,底层数据目录结构为:

此时在 数据库中创建一个名为 hello_lake 的数据表,分区键为日期键(形式为YYYYMMDD),当插入第一批次数据后,假设插入的数据都属于 20210323 这个分区,那么底层表的数据目录结构为:

ClickHouse 每插入一批次数据,则会在底层形成一个或者多个分区目录,具体看插入数据中是否有多个分区的数据。假设现在有插入了一批 20210323 这个分区的数据,那么底层会多一个目录, 2021032322_0,分区相同,但是分区后面的数字不同。关于分区后面数字的解析,具体细节,可以参见《ClickHouse 原理解析与应用实践》6.2.2 章节。

在分区目录中,就是存放的具体数据,分区目录中有这些文件:

primary.idx 是索引文件,会按照你创建表时,指定的 primary key 排序(如果不指定,默认和 order by key 相同),[Column].bin 为列压缩后数据,[Column]表示列的名称,当有多个列时,就会有多个这样的文件。[Column].mrk 表示索引编号与 bin 文件中便宜量的映射。

二、ClickHouse 数据查询流程

2.1 业务方表使用形式

在生产环境中,业务方在使用 ClickHouse 时,一般会使用到两种类型的表:

数据的写入是直接写入到各个分片上面的本地表,本地表用来真正数据存储,Distributed 表引擎的表则用于数据的查询,Distributed 表引擎本身不存储数据, 但可以在多个服务器(分片)上进行分布式查询。简单理解,Distributed 表引擎只是你真实数据表(本地表)的代理,在进行数据查询时,它会将查询请求发送到各个分片上,结合索引(如果有),并行进行查询计算,最终将结果进行合并,返回到 Client。

2.2 Distributed 表数据查询流程

下面是一次对于 Distributed 表引擎类型表查询的流程:

整体上查询过程分为 6 个步骤:

在分片上执行查询语句时,会根据查询语句中的分区范围,先进行分区级别的数据过滤。之后在满足分区条件的目录中,通过 primary.idx 文件,结合索引键的取值范围,查询出索引编号的范围,然后通过查询列的 [Column].mrk 文件,找到其 [Column].bin 文件中的偏移量对应关系,最终将数据加载到内存进行分析和计算。

三、其他