本篇文章主要在架构&使用上介绍ClickHouse的基本概念&基本查询,抛砖引玉,大家实践的路上多多交流。
说在前头:OLAP的分类与OLAP操作
OLAP的架构分类
1.ROLAP:使用关系模型进行建模,数据建模通常使用星型模型或雪花模型。OLAP最初提出的时候就是建立在关系型数据库上,将多维度分析操作直接转换为SQL查询。
2.MOLAP:为了缓解ROLAP的性能问题,MOLAP使用多维数组的形式保存数据,其核心思想是借助预先聚合的结果,使用空间换时间的形式提升查询性能。依托数据立方体模型框定需要分析的维度字段。其缺点显而易见,维度的膨胀、数据的滞后、维度的固化、明细数据的丢失。
3.HOLAP:混合架构。
OLAP操作:
1.下钻 :从高层次的向底层次的明细数据穿透。例如:省维度的销售数据,下钻到市维度。
2.上卷:从低层次向高层次聚合。例如通常使用的group by操作。
3.切片:观察数据立方体的一层。例如订单数据三位立方体:时间,运力,地域;对单个运力维度如特价车进行固化,基于二维数据进行分析。
4.切块:多个切片。
5.旋转:主统计维度的切换,行列转换等
OLAP数据库的设计上也是主要为了高性能的进行以上操作。
ClickHouse架构
什么是ClickHouse? | ClickHouse Docs
ClickStream&WareHouse:基于数据流面向数仓进行OLAP分析。基于MPP架构,使用多主对等网络结构实现高可用,基于关系模型(ROLAP)的列式存储数据库。具有完成的DBMS、列式存储、不需要数据预处理、支持批量更新、拥有完整的SQL支持与函数、支出高可用、不依赖Hadoop生态、开箱即用;不支持事务、不擅长主键查询、不擅长按行删除数据。
1.核心特性:
1.列式存储与数据压缩:
压缩算法(LZ4 标准压缩比8:1)的本质是按照一定的步长进行数据匹配扫描,对重复部分进行转码如:abcdefghi_bcdefghi-->abcdefghi_(9,8)
提升查询性能的优化方式:1.减少数据的扫描范围 2.减少数据的传输大小 无意这两点列式存储具有基础设计上的优势。
2.向量化执行引擎
传统OLTP数据库通常以点查询为主,SQL的计算量很小, 实现这些技术的收益不够明显,但是在分析场景下单条SQL涉及的计算量可能极大,为每行作为一个基本单元进行数据处理可能带来严重的性能损耗:
- 每行数据都要调用相应的函数,函数调用开销占比高
- 存储层按列存储数据,在内存中按列组织数据,但是计算层按行计算无法充分利用cpu的cache预读能力,造成cpu cache miss严重
- 按行处理无法高效利用simd
3.多样化表引擎
把存储引擎作为一层独立的接口:拥有合并树、内存、文件、接口和其他六大类20多种表引擎。
表引擎决定了一张数据表的最终“性格”
- 数据拥有何种特性
- 数据以何种形式被存储
- 数据如何被加载
4.数据分区、分片and多线程与分布式
ClickHouse在数据存取方面,及支持分区partition(纵向扩展,利用多线程原理),也支持分片shard(水平拓展,利用分布式原理)。
向量化执行通过数据级并行的方式提升了性能,多线程则通过线程及并行提升性能。向量化基于底层硬件的能力,多线程由更高的软件层面控制发挥多核CPU的能力。
ClickHose并不像其他分布式系统那样拥有高度的自动化分片能力,ClickHouse提供了本地表(local table)& 分布式表(Distribute table)的概念,一张本地表等同于一份数据分片。而分布式表本身不存储任何数据,历史TDDL作为分库中间件提供访问代理的能力。
5.多主架构
master-slave 与multi-master
数据写入:
replicate-系列表引擎会在ZK中创建一系列监听节点,并以此实现多实例间的通行。在整个通信过程中zk并不涉及数据的传输。
2.合并树表引擎家族
合并树系列索引支持主键索引、数据分区、数据副本、数据采样这些特性。
1.mergeTree
MergeTree在写入一批数据时,数据总会以数据片段的形式写入磁盘,且数据片段不可修改。为了避免片段过多,ClickHouse会通过后台线程定期合并这些数据片段,属于相同分区的数据片段会被合成一个新的片段。这种数据片段往复合并的特点也正是合并树的名称由来。
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [TTL expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2] [TTL expr2],
...
INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1,
INDEX index_name2 expr2 TYPE type2(...) GRANULARITY value2
) ENGINE = MergeTree()
ORDER BY expr
[PARTITION BY expr]
[PRIMARY KEY expr]
[SAMPLE BY expr]
[TTL expr [DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'], ...]
[SETTINGS name=value, ...]
存储结构:
2.ReplacingMergeTree
MergeTree拥有主键,该主键没有唯一约束的语义。ReplacingMergeTree在一定程度上(在同一个分区内进行数据去重,不同分区的重复数据不会被剔除)解决了数据重复的问题,以order by 排序键作为去重依据,去重策略有两种1.依据ver版本,保留最大值2.保留重复数据的最后一行。
3.SummingMergeTree
终端用户只关心查询数据的汇总结果(列值SUM运算结果),不关心明细数据的,且数据大河汇总条件预先明确(group by条件明确,且不会随意改变)。
clickhouse的实践中,通常指定以order by(primary ke默认使用order by表达式);在summingMergerTree&AggregatingMergeTree场景会同时定义两个声明主要是为了满足:1.主键与聚合条件定义的分离。2.为修改聚合条件留下空间。
如:
primary key A
order by A,B, C, D
4.AggregatingMergeTree
SummingMergeTree的升级版,对每列定义aggregateFunction
实践1:
5.CollapsingMergeTree
支持修改的MergeTree
6.VersionedCollapsingMergeTree
CollapsingMergeTree基础上基于版本折叠
3.副本、数据分片shard&集群、数据分区(PARTITION)
副本
- 表级别的副本,而不是服务器级别的
- 多主架构
- Block数据块,insert命令写入数据时会依据max_insert_block_size的大小(default 1048576行)将数据切分成若干block,block是数据写入的基本单元既有原子性和唯一性(hash).
数据分片&数据分区
通过引入副本可以有效降低数据丢失的风险,并提升查询性能,但是有一个问题没有解决那就是数据表的容量问题。进一步数据水平切分即数据分片。ClickHouseshiyong Distributed表引擎作物分布式表的一层透明代理,在集群内部自动开展数据的写入、分发、查询、路由等工作。
数据分区-允许查询在指定了分区键的条件下,尽可能的少读取数据
数据分片-允许多台机器/节点同并行执行查询,实现了分布式并行计算
集群
4.数据查询
1.开源版本主键索引与跳数索引
以默认的索引粒度(8192)为例,MergeTree只需要12208行索引标记就能为1亿行数据记录索引。
3.关键点
- 线上SQL预计不要使用通用模板,基于if生成条件。
- 每个在线查询场景上线前检查执行计划是否满足预期。
5.其他概念
UPDATE in CK
这类操作被称为mutation查询,可以看做alter语句的变种,虽然update和delete操作最终实现了数据的修改和删除但是这是一个非常重的操作,不支持事务,distributed表引擎不支持。其实际执行过程是以分区目录为单位进行的分区重写操作。
吾辈今日苟有所见,而欲为行远之计,又可不早具坚车乎哉!