我们都知道,框架的设计可以分为自顶向下和自下而上,在传统观念中,或者说在我的观念中,做架构设计首先自然做的是顶层设计:
-
事先应该做高层次的抽象设计;
-
规划好各个模块的职责、切分的界面;
-
分配好工程结构、包结构,最好能再来一些设计图,等等。
-
而ClickHouse的设计,则采用了 自下而上。
-
他们是如何实践 自下而上 设计的呢?
从硬件功能层面着手设计,在设计伊始,就至少需要想清楚这么几个问题:
-
我们将要使用的硬件水平是怎样的?包括CPU、内存、硬盘、网络等等;
-
在这样的硬件上,我们需要达到怎样的性能?包括延迟、吞吐量等等;
-
我们准备使用怎样的数据结构?包括String、HashTable、Vector等等;
-
选择的这些数据结构,在我们的硬件上会如何工作?
别小看这些细节,一点一滴的将它们累加起来,数据是非常可观的。也正因为注意了这些细节,所以ClickHouse在基准查询中,能做到1.75亿/每秒的数据扫描性能。那下面我将从如下几点来分享ClickHouse为什么如此之快。
1.高层次架构:
1.1 shared nothing
shared noting 是一种分布式计算架构。在这种架构中,每一个节点都是独立的,自给的,在系统中不存在单点竞争。更明确地说,没有节点共享存储和硬盘。
1.2 并行计算
多核多节点并行化大型查询,也便于扩容。
1.3 列式存储
不同的列存储在不同的文件。
1.4 Merge Tree
ClickHouse支持主键表,为了快速执行对主键范围的查询,数据使用合并树进行递增排序。由于这个原因,数据可以不断地添加到表中。添加数据时无锁处理。
1.5 稀疏索引
在稀疏索引中,只为索引码的某些值建立索引项。同理因为稀疏索引也是聚集索引。每一个索引项包括索引值以及指向该搜索码值的第一条数据记录的指针。
1.6 数据压缩
一些面向列的DBMS不使用数据压缩。但是数据压缩确实提高了性能。
ClickHouse提供了两种数据压缩方式供我们选择:LZ4和ZSTD, 默认使用LZ4压缩方式。
1.7 SQL支持
1.8 索引
带有主键可以在特定的时间范围内为特定客户抽取数据,并且延迟时间小于几十毫秒。
1.9 支持在线查询
这让我们使用该系统作为Web界面的后端。低延迟意味着可以无延迟地实时处理查询,而Yandex.Metrica界面页面加载使用此功能。
1.10 数据复制和对数据完整性的支持
使用异步多主复制。写入任何可用的副本后,数据将分发到所有剩余的副本。系统在不同的副本上保持相同的数据。数据在失败后自动恢复,或对复杂情况使用“按钮”。
2.低层次架构
低层次(硬件)级别的优化,基于CPU指令的向量化执行。
-
SIMD text parssing //文本解析
-
SIMD data filtering //数据过滤
-
SIMD decompression //减压
-
SIMD string operations。//字符串操作
3.算法优化
及时引入世界一流的先进算法。
特定场景,特定优化(函数的优化、查询的优化)
-
vilnitsky Substring Search
-
Hyperscan 和 SR2
-
SIMD JSON
-
Roaring Bitmaps
4.持续测试、持续改进
-
快速迭代、快速改进
-
使用真是数据测试
最后,就以ClickHouse的口号,作为结束吧:
The ClickHouse Style:
As efficient as possible
As fast as possible
正如口号所言,他们做到了。
所以,ClickHouse的黑魔法并不是一项单一的技术,而是一种自底向上的,追求极致性能的设计思路。