是用于联机分析(OLAP)的列式数据库管理系统(DBMS)
常见的行式数据库系统有: MySQL、Postgres和MS SQL Server。将同一列的数据存储在一起,不同列的数据也总是分开存储的数据库是列式数据库。常见的列式数据库有: Vertica、 Paraccel (Actian Matrix,Amazon Redshift)、 Sybase IQ、 Exasol、 Infobright、 InfiniDB、 MonetDB (VectorWise, Actian Vector)、 LucidDB、 SAP HANA、 Google Dremel、 Google PowerDrill、 Druid、 kdb+。
输入输出方面:
cpu方面:
由于执行一个查询需要处理大量的行,因此在整个向量上执行所有操作将比在每一行上执行所有操作更加高效。同时这将有助于实现一个几乎没有调用成本的查询引擎。如果你不这样做,使用任何一个机械硬盘,查询引擎都不可避免的停止CPU进行等待。所以,在数据按列存储并且按列执行是很有意义的。
从clickhouse给的结果来看,clickhouse非常优秀,但是不能从一方的来看,clickhouse的sql兼容性没有Greenplum或tidb好,clickhouse有独有的SQL标准,特别是一些方便olap的查询函数。很多团队,在做老job迁移时,需要对SQL进行一定程度的改造。
单个大查询吞吐量 | 数据在page cache中 | 简单查询 | 单服务器30GB/s |
不太复杂查询 | 单服务器2-10GB/s | ||
数据在磁盘中 | 磁盘读:400MB/s 压缩率:3 |
单服务器1.2GB/s | |
查询延迟时间 | 使用主键并且数据被缓存 | 小于50毫秒(在最佳的情况下应该小于10毫秒) | |
其他情况 | 查找时间(10 ms) * 查询的列的数量 * 查询的数据块的数量 |
||
查询的吞吐量 | ClickHouse可以在单个服务器上每秒处理数百个查询(在最佳的情况下最多可以处理数千个)。但是由于这不适用于分析型场景。因此我们建议每秒最多查询100次。 | ||
数据写入性能 | 建议不少于1000行的批量写入,或每秒不超过一个写入请求 | ||
写入速度大约为50到200MB/s,可以使用多个INSERT进行并行写入 |
(回答来自:https://blog.csdn.net/wenyusuran/article/details/107832079)
着眼硬件,先想后做
基于将硬件功效最大化的目的,ClickHouse会在内存中进行GROUP BY,并且使用HashTable装载数据。与此同时,他们非常在意CPU L3级别的缓存,因为一次L3的缓存失效会带来70~100ns的延迟。这意味着在单核CPU上,它会浪费4000万次/秒的运算;而在一个32线程的CPU上,则可能会浪费5亿次/秒的运算。所以别小看这些细节,一点一滴地将它们累加起来,数据是非常可观的。正因为注意了这些细节,所以ClickHouse在基准查询中能做到1.75亿次/秒的数据扫描性能。
算法在前,抽象在后
性能是ClickHouse算法选择的首要考量指标。
勇于尝鲜,不行就换
如果世面上出现了号称性能强大的新算法,ClickHouse团队会立即将其纳入并进行验证。行就用,不行就不用。
特定场景,特殊优化
ClickHouse会针对不同场景使用最合适、最快的算法。针对同一个场景的不同状况,选择使用不同的实现方式,尽可能将性能最大化。
持续测试,持续改进
由于Yandex的天然优势,ClickHouse经常会使用真实的数据进行测试,这一点很好地保证了测试场景的真实性。ClickHouse差不多每个月都能发布一个版本。
(回答来自:https://blog.csdn.net/wenyusuran/article/details/107832079)
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多个实现类,这些实现类大致可以分为三类:
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个服务节点。
分片只是一个逻辑概念,其物理承载还是由副本承担的。