火の狐 的个人博客

记录精彩的程序人生

Open Source, Open Mind,
Open Sight, Open Future!
  menu
292 文章
2704 浏览
1 当前访客
ღゝ◡╹)ノ❤️

clickHouse的优缺点和核心特性

图片

ClickHouse is a column-oriented database management system (DBMS) for online analytical processing of queries (OLAP).

ClickHouse全称是Click Stream,Data Warehouse,简称ClickHouse就是基于页面的点击事件流,面向数据仓库进行OLAP分析。ClickHouse是一款开源的数据分析数据库,由战斗民族俄罗斯Yandex公司研发的,Yandex是做搜索引擎的,就类似与Google,百度等。

我们都知道搜索引擎的营收主要来源与流量和广告业务,所以搜索引擎公司会着重分析用户网路流量,像Google有Anlytics,百度有百度统计,那么Yandex就对应于Yandex.Metrica。ClickHouse就式在Yandex.Metrica下产生的技术。

根据官网的介绍(https://clickhouse.tech/benchmark/dbms/),ClickHouse在相同的服务器配置与数据量下,平均响应速度:

  • Vertica的2.63倍(Vertica是一款收费的列式存储数据库)
  • InfiniDB的17倍(可伸缩的分析数据库引擎,基于Mysql搭建)
  • MonetDB的27倍(开源的列式数据库)
  • Hive的126倍
  • MySQL的429倍
  • Greenplum的10倍
  • Spark的1倍

ClickHouse主要特点

  • ROLAP(关系型的联机分析处理,和它一起比较的还有OLTP联机事务处理,我们常见的ERP,CRM系统就属于OLTP)
  • 在线实时查询
  • 完整的DBMS(关系数据库)
  • 列式存储(区别与HBase,ClickHouse的是完全列式存储,HBase具体说是列族式存储)
  • 不需要任何数据预处理
  • 支持批量更新
  • 拥有完善的SQl支持和函数
  • 支持高可用(多主结构,在后面的结构设计中会讲到)
  • 不依赖Hadoop复杂生态(像ES一样,开箱即用)
一些不足
  • 不支持事务(这其实也是大部分OLAP数据库的缺点)
  • 不擅长根据主键按行粒度查询(但是支持这种操作)
  • 不擅长按行删除数据(但是支持这种操作)

ClickHouse基础架构

图片

1.Column与Field

Column和Field是ClickHouse数据最基础的映射单元。内存中的一列数据由一个Column对象表示。Column对象分为接口和实现两个部分,在IColumn接口对象中,定义了对数据进行各种关系运算的方法。在大多数场合,ClickHouse都会以整列的方式操作数据,但凡事也有例外。如果需要操作单个具体的数值 ( 也就是单列中的一行数据 ),则需要使用Field对象,Field对象代表一个单值。与Column对象的泛化设计思路不同,Field对象使用了聚合的设计模式。在Field对象内部聚合了Null、UInt64、String和Array等13种数据类型及相应的处理逻辑。

2.DataType

数据的序列化和反序列化工作由DataType负责。IDataType接口定义了许多正反序列化的方法,它们成对出现。IDataType也使用了泛化的设计模式,具体方法的实现逻辑由对应数据类型的实例承载。DataType虽然负责序列化相关工作,但它并不直接负责数据的读取,而是转由从Column或Field对象获取。

3.Block与Block流

ClickHouse内部的数据操作是面向Block对象进行的,并且采用了流的形式。Block对象可以看作数据表的子集。Block对象的本质是由数据对象、数据类型和列名称组成的三元组,即Column、DataType及列名称字符串。仅通过Block对象就能完成一系列的数据操作。Block并没有直接聚合Column和DataType对象,而是通过ColumnWithTypeAndName对象进行间接引用。Block流操作有两组顶层接口:IBlockInputStream负责数据的读取和关系运算,IBlockOutputStream负责将数据输出到下一环节。IBlockInputStream接口定义了读取数据的若干个read虚方法,而具体的实现逻辑则交由它的实现类来填充。IBlockInputStream接口总共有60多个实现类,这些实现类大致可以分为三类:

  • 第一类用于处理数据定义的DDL操作
  • 第二类用于处理关系运算的相关操作
  • 第三类则是与表引擎呼应,每一种表引擎都拥有与之对应的BlockInputStream实现

IBlockOutputStream的设计与IBlockInputStream如出一辙。这些实现类基本用于表引擎的相关处理,负责将数据写入下一环节或者最终目的地。

4.Table

在数据表的底层设计中并没有所谓的Table对象,它直接使用IStorage接口指代数据表。表引擎是ClickHouse的一个显著特性,不同的表引擎由不同的子类实现。IStorage接口负责数据的定义、查询与写入。IStorage负责根据AST查询语句的指示要求,返回指定列的原始数据。后续的加工、计算和过滤则由下面介绍的部分进行。

5.Parser与Interpreter

Parser分析器负责创建AST对象;而Interpreter解释器则负责解释AST,并进一步创建查询的执行管道。它们与IStorage一起,串联起了整个数据查询的过程。Parser分析器可以将一条SQL语句以递归下降的方法解析成AST语法树的形式。不同的SQL语句,会经由不同的Parser实现类解析。Interpreter解释器的作用就像Service服务层一样,起到串联整个查询过程的作用,它会根据解释器的类型,聚合它所需要的资源。首先它会解析AST对象;然后执行"业务逻辑" ( 例如分支判断、设置参数、调用接口等 );最终返回IBlock对象,以线程的形式建立起一个查询执行管道。

6.Functions 与Aggregate Functions

ClickHouse主要提供两类函数—普通函数(Functions)和聚合函数(Aggregate Functions)。普通函数由IFunction接口定义,拥有数十种函数实现,采用向量化的方式直接作用于一整列数据。聚合函数由IAggregateFunction接口定义,相比无状态的普通函数,聚合函数是有状态的。以COUNT聚合函数为例,其AggregateFunctionCount的状态使用整型UInt64记录。聚合函数的状态支持序列化与反序列化,所以能够在分布式节点之间进行传输,以实现增量计算。

7.Cluster与Replication

ClickHouse的集群由分片 ( Shard ) 组成,而每个分片又通过副本 ( Replica ) 组成。这种分层的概念,在一些流行的分布式系统中十分普遍。这里有几个与众不同的特性。ClickHouse的1个节点只能拥有1个分片,也就是说如果要实现1分片、1副本,则至少需要部署2个服务节点。分片只是一个逻辑概念,其物理承载还是由副本承担的。

ClickHouse 表引擎

  1. MergeTree :允许您依据主键和日期创建索引,并进行实时的数据更新操作。MergeTree 是 ClickHouse 里最为先进的表引擎。
  2. ReplacingMergeTree :该引擎和MergeTree的不同之处在于它会删除具有相同主键的重复项。数据的去重只会在合并的过程中出现。有一些数据可能仍未被处理。因此,ReplacingMergeTree适用于在后台清除重复的数据以节省空间,但是它不保证没有重复的数据出现。在一定程度上可以弥补clickhouse不能对数据做更新的操作,可以用做在数据过多重复场景对数据进行去重。
  3. SummingMergeTree:表的数据片段时,ClickHouse 会把所有具有相同主键的行合并为一行,该行包含了被合并的行中具有数值数据类型的列的汇总值。如果主键的组合方式使得单个键值对应于大量的行,则可以显著的减少存储空间并加快数据查询的速度,对于不可加的列,会取一个最先出现的值。对某个字段长期的汇总查询场景。
  4. AggregatingMergeTree :该引擎继承自 MergeTree,并改变了数据片段的合并逻辑。ClickHouse 会将相同主键的所有行(在一个数据片段内)替换为单个存储一系列聚合函数状态的行。可以使用 AggregatingMergeTree 表来做增量数据统计聚合,包括物化视图的数据聚合。引擎需使用 AggregateFunction 类型来处理所有列。如果要 按一组规则来合并减少行数,则使用 AggregatingMergeTree 是合适的。对于AggregatingMergeTree不能直接使用insert来查询写入数据。一般是用insert select。但更常用的是创建物化视图 ,做增量数据统计聚合,包括物化视图的数据聚合。
  5. Distributed 分布式引擎本身不存储数据, 但可以在多个服务器上进行分布式查询。读是自动并行的。读取时,远程服务器表的索引(如果有的话)会被使用。分布式引擎参数:服务器配置文件中的集群名,远程数据库名,远程表名,数据分片键。