Clickhouse的几个关键优势

前言

前阵子我在公司的项目中调研以及应用了 ClickHouse,出于它在海量数据场景下的极致性能表现,也是因为我们的项目面向海量数据高速存储分析场景:系统一次性处理的底层生成数据量级可达 TB、千亿级别,并要求提供秒级的查询响应,而且大多数是单表检索、不涉及多表 JOIN 的复杂查询,需求恰好与 ClickHouse 的专长匹配。通过这次项目实践,同时结合我的调研、学习结果,我总结了 ClickHouse 作为在线分析高性能数据库的几个关键优势。

列式存储

列式存储,意味着数据在物理空间中是同一列存放在一起,和行式存储同一行数据连续存放不同。这种存储方式有利 于大数据分析场景,原因是查询效率高:在只需要检索个别列的时候,避免扫描整行数据,大大减少了 IO。

CH 每一列数据单独存储在 bin 文件中,按ORDER BY指定的键排序。ORDER BY的键可以支持多个。假设有三列排序键(A,B,C),数据在 part 内部物理存储顺序(按行颗粒):

排序的原则是,先按 A 排序,若 A 相同,则按 B 排序;若 A、B 相同,则按 C 排序。对于非排序键的列,数据同样按此规则排序,只不过是独立存储在自己的 bin 文件中。

按过滤条件检索的时候,为了使排序键生效,需满足最左匹配原则(和关系型数据库中联合索引的命中规则相同)。例如,对于排序键 ORDER BY (A, B, C):

  • ✅ 有效:WHERE A=1 AND B>10 → 可以用排序键跳过大量颗粒(granule)

  • ✅ 有效:WHERE A>5 → 只用到第一列

  • ❌ 无效:WHERE B>10(没有 A)→ 无法用主键索引,只能全颗粒扫描

  • ❌ 无效:WHERE A=1 AND C>20(跳过 B)→ A 可以过滤,C 无法借助主键索引过滤

压缩

列式存储下,一列同类型的值连续存储,有利于压缩。ClickHouse 内置了多种数据压缩算法;对于一些数值具备规律的列,可以显式声明设置特定算法,以达到更高的压缩效率。如果是基数庞大但是取值较少的列,使用LowCardinality类型。它是 ClickHouse 用于优化低基数(重复值多)列的核心手段,本质是字典编码。原理是用一个字典结构存储值与编码的映射关系。例如国家编码列,值有 us,ch,en,aps,映射到字典就只有 1,2,3,4 这样的字典 key,存储空间大幅减少。

  • LZ4,CH 默认的压缩算法,寻找数据流中的重复片段实现压缩,特点是解压缩速度快,但压缩比不如 ZSTD。

  • ZSTD 压缩比更高,但是相对地,解压缩速度比 LZ4 慢。

  • DoubleDelta 算法,二阶差分编码:先计算相邻数值差值,再对差值再次求差,适合均匀递增的时间戳类时序数据。

  • T64,为整数设计,切除高位为 0 的部分,只保留有效 bit,以此大幅减少数据占用空间。

索引

ClickHouse 的索引是稀疏索引。它是一个有序的存储结构,可以通过二分查找定位到具体数据位置,有利于范围查找。每一个索引条目对应由 8192 行构成的块。这样有效地减少了索引的存储开销和检索索引的耗时。一个表存储为多个 part 目录,每个目录下有索引文件、各列标记文件和各列二进制文件。查找时在索引文件中通过二分查找到颗粒序号。这个颗粒序号就是一个下标,再到指定的列标记文件中通过这个下标查找对应 bin 文件中的偏移量,然后到二进制文件中读取数据、解压。

复制代码
part_xxx/
├── primary.idx   # 主键稀疏索引
├── id.bin    # id列原始压缩数据
├── id.mrk    # id列标记文件
├── byte_index.bin
├── byte_index.mrk
├── data_id.bin
├── data_id.mrk
└── checksums.txt

查询过程:

  1. 【分区裁剪】(如果有PARTITION BY,最先执行,淘汰整个分区)

  2. 【Part 粗过滤】遍历所有剩余 Part,比较 min-sort-key/max-sort-key,淘汰无关 Part

  3. 【每个保留 Part 内部:primary.idx 数组二分】筛选颗粒编号列表

  4. 【mrk 标记文件:颗粒编号直接数组下标 O (1) 寻址】获取 bin 偏移

  5. 【读取.bin 压缩块】解压、行过滤,返回数据

向量化计算

列式存储使得从磁盘读取数据时可以批量读取,在计算的时候也以多个数据为单位,使用 SIMD(Single Instruction, Multiple Data,单指令多数据),一条指令计算多个值。因为减少了大量逐个循环导致的分支跳转、条件判断,充分利用硬件特性与能力,所以性能提升更加明显。

并行执行

从单节点上看,ClickHouse 使用多线程执行查询和写入操作,发挥 CPU 多核优势。查询和插入分别由max_threads和max_insert_threads限制最大并行度。并行度默认会设置为物理核数的两倍。

从集群上看,ClickHouse 使用 MPP 架构,但只针对分布式(Distributed)表:写入数据时会根据分片键计算路由,将数据写入不同节点;查询的时候也根据分片键路由到指定节点执行,结果再汇总到客户端。

基于以上几个优势,CH 才能在 OLAP 领域中脱颖而出,成为各大厂最钟爱的即席查询引擎之一!

相关推荐
贝壳6901 分钟前
一个2026年2月才上传的库,凭什么敢碰2009年就有人写烂的题目
算法
贝壳69035 分钟前
同一道三亿位选型题,三个AI给了我三个答案,我把它们拉进同一台机器复跑
算法
青少儿编程课堂3 小时前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会图形化考级:校园大富翁经营闯关解析
c++·python·算法·bfs·信息学竞赛
在所不辞兄3 小时前
为什么在新能源汽车电驱与热管理开发中,AI驱动的数字孪生和数据驱动仿真正在部分替代对物理台架与实车标定的依赖?
人工智能·深度学习·神经网络·算法·机器学习
I_belong_to_jesus14 小时前
C++关于分支预测的优化1
开发语言·c++·算法
Code_Solitude21 小时前
C语言动态内存 + 柔性数组 + 数组名退化
c语言·算法·柔性数组
上海潭龙东海科技有限公司21 小时前
客运站管控之动态孪生技术方案(新增一屏管控模块
数据仓库·人工智能·算法·重构·动态规划
YLCHUP1 天前
【思维&图论建模】题解:债权(debt)_图论_建模_思路转化_思维题目_C++算法竞赛
c++·笔记·算法·数学建模·贪心算法·深度优先·图论
思麟呀1 天前
背包DP(01背包+完全背包)
c++·算法