交互式分析领域,为何 ClickHouse 能够杀出重围?
The following article is from 云加社区 Author 姜国强
一、交互式分析之 ClickHouse
1. 交互式分析简介
交互式分析,也称 OLAP(Online Analytical Processing),它赋予用户对海量数据进行多维度、交互式的统计分析能力,以充分利用数据的价值进行量化运营、辅助决策等,帮助用户提高生产效率。
交互式分析主要应用于统计报表、即席查询(Ad Hoc)等领域,前者查询模式较固定,后者即兴进行探索分析。代表场景例如:移动互联网中 PV、UV、活跃度等典型实时报表;互联网内容领域中人群洞察、关联分析等即席查询。
大多数访问是读请求。
写入通常为追加写,较少更新、删除操作。
读写不关注事务、强一致等特性。
查询通常会访问大量的行,但仅部分列是必须的。
查询结果通常明显小于访问的原始数据,且具有可理解的统计意义。
2. 百花齐放下的 ClickHouse
其中,ClickHouse 作为一款 PB 级的交互式分析数据库,最初是由号称 “ 俄罗斯 Google ” 的 Yandex 公司开发,主要作为世界第二大 Web 流量分析平台 Yandex.Metrica(类 Google Analytic、友盟统计)的核心存储,为 Web 站点、移动 App 实时在线的生成流量统计报表。
二、ClickHouse 架构
1. 集群架构
Shard :集群内划分为多个分片或分组(Shard 0 … Shard N),通过 Shard 的线性扩展能力,支持海量数据的分布式存储计算。
Node :每个 Shard 内包含一定数量的节点(Node,即进程),同一 Shard 内的节点互为副本,保障数据可靠。ClickHouse 中副本数可按需建设,且逻辑上不同 Shard 内的副本数可不同。
ZooKeeper Service :集群所有节点对等,节点间通过 ZooKeeper 服务进行分布式协调。
2. 数据模型
(1)逻辑数据模型
# 首先,创建本地表
CREATE TABLE table_local ON CLUSTER cluster_test
(
OrderKey UInt32, # 列定义
OrderDate Date,
Quantity UInt8,
TotalPrice UInt32,
……
)
ENGINE = MergeTree() # 表引擎
PARTITION BY toYYYYMM(OrderDate) # 分区方式
ORDER BY (OrderDate, OrderKey); # 排序方式
SETTINGS index_granularity = 8192; # 数据块大小
# 然后,创建分布式表
CREATE TABLE table_distribute ON CLUSTER cluster_test AS table_local
ENGINE = Distributed(cluster_test, default, table_local, rand()) # 关系映射引擎
MergeTree :ClickHouse 中使用非常多的表引擎,底层采用 LSM Tree 架构,写入生成的小文件会持续 Merge。
Distributed :ClickHouse 中的关系映射引擎,它把分布式表映射到指定集群、数据库下对应的本地表上。
(2)物理存储模型
数据分区:每个分片副本的内部,数据按照 PARTITION BY 列进行分区,分区以目录的方式管理,本文样例中表按照时间进行分区。
列式存储:每个数据分区内部,采用列式存储,每个列涉及两个文件,分别是存储数据的 .bin 文件和存储偏移等索引信息的 .mrk2 文件。
数据排序:每个数据分区内部,所有列的数据是按照 ORDER BY 列进行排序的。可以理解为:对于生成这个分区的原始记录行,先按 ORDER BY 列进行排序,然后再按列拆分存储。
数据分块:每个列的数据文件中,实际是分块存储的,方便数据压缩及查询裁剪,每个块中的记录数不超过 index_granularity,默认 8192。
主键索引:主键默认与 ORDER BY 列一致,或为 ORDER BY 列的前缀。由于整个分区内部是有序的,且切割为数据块存储,ClickHouse 抽取每个数据块第一行的主键,生成一份稀疏的排序索引,可在查询时结合过滤条件快速裁剪数据块。
三、ClickHouse核心特性
1. 列存储
ClickHouse 采用列存储,这对于分析型请求非常高效。一个典型且真实的情况是:如果我们需要分析的数据有 50 列,而每次分析仅读取其中的 5 列,那么通过列存储,我们仅需读取必要的列数据,相比于普通行存,可减少 10 倍左右的读取、解压、处理等开销,对性能会有质的影响。
这是分析场景下,列存储数据库相比行存储数据库的重要优势。这里引用 ClickHouse 官方一个生动形象的动画,方便大家理解:
2. 向量化执行
以商品订单数据为例,查询某个订单总价格的处理过程,由传统的按行遍历处理的过程,转换为按 Block 处理的过程,具体如下图:
3. 编码压缩
4. 多索引
ClickHouse 中最基础的索引是主键索引。前面我们在物理存储模型中介绍,ClickHouse 的底层数据按建表时指定的 ORDER BY 列进行排序,并按 index_granularity 参数切分成数据块,然后抽取每个数据块的第一行形成一份稀疏的排序索引。
5. 物化视图(Cube/Rollup)
用户在使用时,可优先按照 ROLAP 思路进行调优,例如主键选择、索引优化、编码压缩等。当希望性能更高时,可考虑结合 MOLAP 方式,针对高频查询模式,建立少量的物化视图,消耗可接受的计算、存储资源,进一步换取查询性能。
6. 其他特性
SQL 方言:在常用场景下,兼容 ANSI SQL,并支持 JDBC、ODBC 等丰富接口。
权限管控:支持 Role-Based 权限控制,与关系型数据库使用体验类似。
多机多核并行计算:ClickHouse 会充分利用集群中的多节点、多线程进行并行计算,提高性能。
近似查询:支持近似查询算法、数据抽样等近似查询方案,加速查询性能。
Colocated Join:数据打散规则一致的多表进行 Join 时,支持本地化的 Colocated Join,提升查询性能。
……
四、ClickHouse 的不足
1. 分布式管控
基于 ClickHouse 的当前架构,实现自动均衡相对复杂,导致相关问题的根因在于 ClickHouse 分组式的分布式架构:同一分片的主从副本绑定在一组节点上,更直接的说,分片间数据打散是按照节点进行的,自动均衡过程不能简单的搬迁分片到新节点,会导致路由信息错误。而创建新表并在集群中进行全量数据重新打散的方式,操作开销过高。
2. 计算引擎
3. 实时写入
但 ClickHouse 并不适合实时写入,原因在于 ClickHouse 并非典型的 LSM Tree 架构,它没有实现 Memory Table 结构,每批次写入直接落盘作为一棵 Tree(如果单批次过大,会拆分为多棵 Tree),每条记录实时写入会导致底层大量的小文件,影响查询性能。
五、结语
ClickHouse 仍然年轻,虽然在某些方面存在不足,但极致性能的存储引擎,使得 ClickHouse 成为一个非常优秀的存储底座。
- EOF -
看完本文有收获?请转发分享给更多人
推荐关注「数据分析与开发」,提升数据技能
点赞和在看就是最大的支持❤️