clickhouse

什么是ClickHouse?
ClickHouse是一个用于联机分析(OALP)的列式数据库管理系统(DBMS)。
在传统的行式数据库系统中,处于同一行中的数据中的数据总是被物理的存储在一起。

不同的数据存储方式适用于不同的业务场景,数据访问的场景包括:进行了何种查询、多久查询一次以及各种查询的比例;是否使用事务;数据的复制机制以及数据的完整性要求;每种类型的查询要求的延迟与吞吐量

系统负载越高,依据使用场景定制化越重要,并且定制将变得越精细。没有一个系统能够同时适用于所有不同的业务场景。

OLAP场景的关键特征(Clickhouse的适用场景)

  • 读多于写:不同于事务处理,数据分析(OLAP)场景通常是将数据批量导入后,进行任意维度的灵活探索、报表制作等。数据一次性写入后,分析师需要尝试从各种角度对数据做挖掘、分析,直到发现其中的商业价值、业务变化趋势。数据读取的次数远多于写入次数,这要求底层数据库为这个特点专门设计,而不是采用传统数据库的技术架构。
  • 大宽表,读大量行但是少量列,结果集较小:OLAP场景中,通常是一张或几张多列的大宽表,列数据高达数百甚至数千列。对数据分析处理时,选择其中的少数几列作为维度列、其他几列作为指标列,然后对全表或较大范围内的数据做聚合计算。
  • 数据批量写入,且数据不更新或少量更新:OLAP类业务,由于数据量很大,通常更加关注写入吞吐,要求数据尽快导入,而不会做更新、删除操作。
  • 无需事务,数据一致性要求低
  • 灵活多变,不需要预先建模:分析场景下,随着业务变化要及时调整分析维度、挖掘方法,以尽快发现数据价值、更新业务指标。而,数据仓库存储着海量的历史数据,调整代价高昂。预先建模技术虽然可以在特定场景下加速计算,但是无法满足业务灵活多变的发展需求,维护成本高。

Clickhouse存储层
Clickhouse从OALP场景需求出发,定制了一套全新的高效列式存储引擎,并且实现了数据有序存储、主键索引、稀疏索引、数据Sharding、数据Partitioning、TTL、主备复制等丰富功能。
列式存储
1,分析类场景往往需要读取大量行,但是少数几个列。行存模式下,数据按行连续存储,所有列的数据都存储在一个block,不参与计算的列也要被全部读出,读取操作被验证放大。
而列存储模式下,只需要读取参与计算的列即可,极大的降低了IO Cost,加速了查询。
2,同一列的数据属于同一类型,压缩效果显著,压缩节省了大量的存储空间,降低了存储成本

数据有序存储
Clickhouse支持在建表时,指定将数据按照某些列进行order by。where条件命中的数据都紧密存储在一个或若干个连续的Block中,而不是分散的存储在任意多个Block,大幅度减少需要IO的block数量。

主键索引
Clickhouse支持主键索引,它将每列数据按照index granularuty(默认是8192行)进行划分,每个index granularity的开头第一行被称为一个mark行。主键索引存储在该mark行对应的primary key的值。

对于where条件中含有primary key的查询,通过对主键索引进行二分查找,能够直接定位到对应的index
granularity,避免了全表扫描从而加速查询。

Clickhouse的主键索引与MySQL等数据库不同,它并不用于去重。即便primary key相同的行,也可以同时存在于数据库中。要想实现去重效果,需要结合具体的表引擎ReplacingMergeTree。

稀疏索引
ClickHouse支持对任意列创建任意数量的稀疏索引,它本质上是对一个完整index granularity(默认8192行)的统计信息,并不会具体记录每一行在文件中的位置。

数据Sharding
ClickHouse支持单机模式,也支持分布式集群模式。在分布式模式下,ClickHouse会将数据分为多个分片,并且分不到不同节点上。不同的分片策略来应对不同的SQL Pattern时,ClickHouse提供了丰富的sharding策略,让业务可以根据实际需求选用。
1,random随机分片:写入数据会被随机分发到分布式集群中的某个节点上
2,constant固定分片:写入数据会被分发到固定一个节点上
3,column value分片:按照某一列的值进行hash分片
sharding机制使得Clickhouse可以横向线性扩展,构建大规模分布式集群,从而具备处理海量数据的能力。

数据Partitioning
Clickhouse支持Partition by子句,在建表时可以指定按照任意合法表达式进行数据分区操作,比如通过toYYYYMM()将数据按月进行分区、toMonday()将数据按照周几进行分区、对Enum类型的列直接每种取值作为一个分区。
数据Partition在ClickHouse中主要有两方面应用:

  • 在partition key上进行分区裁剪,只查询必要的数据
  • 对partition进行TTL管理,淘汰过期的分区数据

数据TTL
在分析场景中,数据的价值随着时间流失而不断降低,多数业务出于成本考虑只会保留最近几个月的数据,Clickhouse通过TTL提供数据生命周期管理的能力。
ClickHouse支持几种不同粒度的TTL:

  • 列级别的TTL:当一列中的部分数据过期后,会被替换成默认值;当全列数据都过期后,会删除该列
  • 行级别的TTL:当某一列过期后,会直接删除该行
  • 分区级别的TTL:当分区过期后,会直接删除该分区

高吞吐写入能力
ClickHouse采用类似LSM Tree的结构,数据写入后定期在后台Compaction。通过类LSM Tree的结构,顺序写磁盘,充分利用了磁盘的吞吐能力。

Clickhouse计算层
Clickhouse在计算层,竭尽所能榨干硬件能力,提升查询速度。它实现了单机多核并行,分布式计算、向量化执行和SIMD指令、代码生成等多种技术。

多核并行
Clickhouse将数据划分为多个Partition,每个Partition再进一步划分为多个index granularity,然后通过多个CPU核心分别处理其中的一部分来实现并行数据处理。

单条Query就能利用整个计算机的所有CPU,极致的并行计算处理能力,极大的降低了查询延时。

分布式计算
除了优秀的单机处理能力,ClickHouse还提供了可线性扩展的分布式计算能力。Clickhouse会自动将查询拆解为多个task下发到集群中,然后进行多机并行处理,最后将结果汇聚在一起。

ClickHouse表类型

create table [if not exists] [db.]table.name [on CLUSTER cluster]
(
name1 [type1] ,
name2 [type2],
.....
)Engine=MergeTree()
partition by toYYYYMMDD(date)
order by (date, ip4, ip6, proto, port)
settings index_granularity=8192;
参数描述
ENGINE表引擎参数,不同的存储引擎提供不同的存储机制、索引方式等功能
order by排序字段,如果没有指定主键、排序字段即为主键。如果不需要排序,则可以使用oreder by tuple()语法。这时,ClickHouse会按照插入的顺序存储数据
partition by分区字段
primary key指定主键,如果排序字段与主键不一致,可以单独指定主键字段;否则,默认主键就是排序字段
sample by采样字段,如果指定了该字段,那么主键中也必然包含了该字段。
TTL数据的存活时间,在MergeTree中,可以为某个列字段或者整张表设置TTL。当时间到达时,如果是列字段级别的TTL,就会删除这一列的数据;如果是表级别的TTL,就会删除整张表的数据
SETTINGS额外的参数配置,可选

ClickHouse的表一共分为四个系列,分别是Log、MergeTree、Integration、Special。其中,包含了两种特殊的表引擎Replicated、Distributed,功能上与其他表引擎相互独立,不可替代。

Log、Special和Integration主要用于特殊用途,场景十分有限。MergeTree系列才是官方主推的存储引擎,支持几乎所有的clickhouse核心功能。

MergeTree
MergeTree表引擎主要用于海量数据分析、支持数据分区、存储有序、主键索引、稀疏索引、数据TTL等。MergeTree支持所有Clickhouse SQL语法,但是在MergeTree中主键并不用于去重。

ReplacingMergeTree
为了解决MergeTree相同主键无法去重的问题,ClickHouse提供了ReplacingMergeTree引擎,用来做去重。

虽然ReplacingMergeTree提供了主键去重的能力,但是仍然有以下的限制:

  • 在没有彻底optimize之前,可能无法达到主键去重的效果,比如部分数据已经被去重,而一部分数据仍然有主键重复
  • 在分布式场景下,相同primary key的数据可能被sharding到不同的节点上,不同shard间可能无法去重
  • optiomize是后台动作,无法预测具体执行时间点
  • 手动执行optimize在海量数据场景下要消耗大量时间,无法满足业务中即时查询的效果

创建和使用ClickHouse复制表和分布式表

分布式存储要想实现高可用,就必须要保证高可用,就必须有数据冗余—即副本(replica)。

ClickHouse依靠ReplicatedMergeTree引擎与Zookeeper实现了赋值表机制,用户在创建表时可以通过指定引擎选择该表是否高可用,每张表的分片和副本都是独立的。
ClickHouse依靠Distributed引擎实现了分布式表机制,在所有分片(本地表)上建立视图进行分布式查询,使用很方便。ClickHouse有数据分片(Shard)的概念,这也是分布式存储的特点,即通过并行读写提高效率。

在实际操作中,为了最大化性能和稳定行,分片和副本几乎总是一同使用的。

1,查询集群标识符cluster等环境参数信息
查询分片标识符和副本标识符replica
2,创建本地复制表
使用ReplicatedMergeTree引擎创建复制表
例如:在default_cluster_1集群节点上和default数据库下创建表名为test的ReplicatedMergeTree表
create table default.test on cluster default_cluster_1
(
EventDate DateTime,
id UInt64
)Engine = ReplicatedMergeTree(’/clickhouse/tables/{shard}/default/test’, ‘replica’)
partition by toYYYYMM(EventDate)
order by id;

  • on cluster语法表示分布式DDL,即执行一次就可以在集群所有实例上创建同样的本地表
  • default_cluster_1 为cluster集群标识符
  • ReplicatedMergeTree引擎接受两个参数(1, Zookeeper中该表相关数据的存储位置,该路径必须在/clickhouse目录下,为了避免不同表在Zookeeper上数据冲突,目录按照/clickhouse/tables/{分片标识符}/数据库名/表名2,副本名称,使用副本标识符即可)

3,使用Distributed引擎创建分布式表

create table default.test_all on cluster default_cluster_1
(
EventDate DateTime,
id UInt64
)
ENGINE = Distributed(集群标识符,数据库名,表名,分片分发方式)

Zookeeper在ClickHouse集群中的作用

ClickHouse中,依赖Zookeeper解决的问题可以分为两大类:分布式DDL执行、ReplicatedMergeTree表主备节点之间的状态同步。
分布式应用基于Zookeeper可以解决很多常见问题,例如心跳管理、主备切换、分布式锁等。
ClickHouse集群的每个节点都会把收到的分布式执行DDL请求放入到一个公共的Zookeeper任务队列中,然后每个节点的后台线程会一次执行任务队列中的DDL,保证分布式DDL的穿行执行顺序。
ReplicatedMergeTree表引擎的同步包括写入同步、异步Merge同步,它们所有的同步逻辑都是强依赖于Zookeeper。

ClickHouse组件架构
整个集群分为多个shard(分片),不同shard之间数据彼此隔离;在一个shard内部,可配置一个或多个replica(副本),互为副本的2个replica之间通过专有复制协议保持最终一致性。

ClickHouse写入链路
ClickHouse提供了两种写入方法:1,写本地表 2,写分布式表
写本地表方式,需要业务层感知底层所有Server的IP,并且自行处理数据的分片操作。由于每个节点都可以分别直接写入,这种方式使得集群的整体写入能力与节点数完全成正比,提供了非常高的吞吐能力和定制灵活性。但是,相对而言,也增加了业务层的依赖,引入了复杂性。
而写分布式表相对简单,业务层只需将数据写入单一endpoint及单一一张分布式表即可,不需要感知底层server拓扑结构等实现细节。在不需要极高写入吞吐能力的业务场景下,建议直接写入分布式表来降低业务复杂性。

ClickHouse存储格式
ClickHouse采用列存格式作为单机存储,并且采用类LSM Tree的结构来进行组合与合并。

在这里插入图片描述

文件作用
checksums.txt校验文件
colums.txt列信息文件,明文格式存储,用于保存此数据分区下的列字段信息
count.txt计数文件,用于记录当前数据分区目录下数据的总行数
primary.idx一级索引文件,使用二进制存储,用于存放稀疏索引。索引通过order by或primary key指定字段,借助稀疏索引,能够有效减少数据扫描范围,加速查询速度。
列.bin列字段标识文件
列.mrk2列字段标记文件,使用二进制格式存储。标志文件中保存了.bin文件中数据的偏移量

ClickHouse中索引由primary key 或order by指定,索引数据保存在primary.idx文件中。Clickhouse创建的索引为稀疏索引,默认索引粒度(index_grandualriity)为8192(即每隔8192行数据抽取一条数据创建一个索引记录)。

在查找时,如果查询中包含主键索引条件,则首先在primary.idex中进行二分查找,如果找到符合条件的颗粒mark。然后在mark文件中获取数据的偏移量信息,加速查找。

Spark JDBC写ClickHouse

ClickHouse对Hadoop生态并不友好,官方没有提供Spark Connector直接用于读写的操作。但双方都支持JDBC,clickhouse 9000端口,支持高性能写入,数据按列组织压缩。

spark jdbc的方式不支持在clickhouse中主动创建表结构,需要在插入前提前创建表。

行存和列存
1,行存储的写入是一次性完成,消耗的时间比列存储少,并且能够保证数据的完整性
2,列存储便于查找,压缩比例高

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值