ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。
在传统的行式数据库中,数据存储方式如下所示:
row | id | status | title | time |
---|---|---|---|---|
#1 | 12312 | 1 | alksdjalkdj | 2016-05-18 05:19:20 |
#2 | 12313 | 1 | alksdjalkdj | 2016-05-18 05:19:20 |
#3 | 12314 | 1 | alksdjalkdj | 2016-05-18 05:19:20 |
#4 | 12315 | 1 | alksdjalkdj | 2016-05-18 05:19:20 |
常见的行式数据库有:mysql,postgresql、sqlserver等。
而列式数据库的存储方式如下所示:
row | #1 | #2 | #3 | #4 |
---|---|---|---|---|
id | 12312 | 12313 | 12314 | 12315 |
status | 1 | 1 | 1 | 1 |
title | alksdjalkdj | alksdjalkdj | alksdjalkdj | alksdjalkdj |
time | 2016-05-18 05:19:20 | 2016-05-18 05:19:20 | 2016-05-18 05:19:20 | 2016-05-18 05:19:20 |
常见的列数数据库有:Vertica、 Paraccel (Actian Matrix,Amazon Redshift)、 Sybase IQ、 Exasol、 Infobright、 InfiniDB、 MonetDB (VectorWise, Actian Vector)、 LucidDB、 SAP HANA、 Google Dremel、 Google PowerDrill、 Druid、 kdb+。
OLAP场景的关键特征
- 绝大多数是读请求
- 数据以相当大的批次(> 1000行)更新,而不是单行更新;或者根本没有更新。
- 已添加到数据库的数据不能修改。
- 对于读取,从数据库中提取相当多的行,但只提取列的一小部分。
- 宽表,即每个表包含着大量的列(对join支持不好)
- 查询相对较少(通常每台服务器每秒查询数百次或更少)
- 对于简单查询,允许延迟大约50毫秒
- 列中的数据相对较小:数字和短字符串(例如,每个URL 60个字节)
- 处理单个查询时需要高吞吐量(每台服务器每秒可达数十亿行)
- 事务不是必须的(不支持事务)
- 对数据一致性要求低
- 每个查询有一个大表。除了他以外,其他的都很小。
- 查询结果明显小于源数据。换句话说,数据经过过滤或聚合,因此结果适合于单个服务器的RAM中
行式数据库与列式数据库在查询步骤上的差别
有一张学生表student,字段有id,name,age,address,phone,id_card等字段。
1)行式数据库(以mysql为例)
假设我们执行select id,name,age from student
首先会搜索innodb引擎的b+树,在叶子节点找到所有的数据,然后再讲需要的字段拆分出来,实际差分过程是在缓冲池中做的,这部分的时间消耗我们暂时忽略。假设表中有10000条数据,那么此次IO就是10000条全量数据的IO。
2)列式数据库
列式的存储我们只需要根据需要查询的id,name,age,取出本行的数据即可,即是所有我们需要的数据,当通过IO到内存时,没有将多余的address,phone等字段返回,这将大大提升此次查询的效率。
我们假设每个字段一个字节,那么行式数据库相当于一次IO要传输6W个字节的数据;而列式的只需要3w。如此就相当于提升了2倍的性能。
假设如果表中有100个列,而你只需要5个,那么就是20倍的提升。
ClickHouse的特性
1)数据压缩
在一些列式数据库管理系统中(例如:InfiniDB CE 和 MonetDB) 并没有使用数据压缩。但是, 若想达到比较优异的性能,数据压缩确实起到了至关重要的作用。
除了在磁盘空间和CPU消耗之间进行高效通用压缩编解码器之外,ClickHouse还提供针对特定类型数据的专用编解码器,这使得ClickHouse能够与更小的数据库(如时间序列数据库)竞争并超越它们。
2)数据的磁盘存储
ClickHouse被设计用于工作在传统磁盘上的系统,它提供每GB更低的存储成本,但如果可以使用SSD和内存,它也会合理的利用这些资源。
3)多核心并行处理
ClickHouse会使用服务器上一切可用的资源,从而以最自然的方式并行处理大型查询。
4)多服务器分布式处理
数据可以保存在不同的shard上,每一个shard都由一组用于容错的replica组成,查询可以并行地在所有shard上进行处理。
5)支持SQL
ClickHouse支持一种[基于SQL的声明式查询语言,它在许多情况下与ANSI SQL标准相同。
支持的查询GROUP BY, ORDER BY, FROM, JOIN, IN以及非相关子查询。
相关(依赖性)子查询和窗口函数暂不受支持,但将来会被实现。
6)向量引擎
为了高效的使用CPU,数据不仅仅按列存储,同时还按向量(列的一部分)进行处理,这样可以更加高效地使用CPU。
实际是按照向量的方向查询数据,顺序读取磁盘,从而减少cpu等待磁盘IO的时间。
7)实时数据更新
ClickHouse支持在表中定义主键。为了使查询能够快速在主键中进行范围查找,数据总是以增量的方式有序的存储在MergeTree中。因此,数据可以持续不断地高效的写入到表中,并且写入的过程中不会存在任何加锁的行为。
8)索引
按照主键对数据进行排序,ClickHouse在几十毫秒以内完成对数据特定值或范围的查找。
9)适合在线查询
在线查询意味着在没有对数据做任何预处理的情况下以极低的延迟处理查询,并将结果加载到用户的页面中。
10)支持近似计算
ClickHouse提供各种各样在允许牺牲数据精度的情况下对查询进行加速的方法:
1、用于近似计算的各类聚合函数,如:distinct values, medians, quantiles
2、基于数据的部分样本进行近似查询。这时,仅会从磁盘检索少部分比例的数据。
3、不使用全部的聚合条件,通过随机选择有限个数据聚合条件进行聚合。这在数据聚合条件满足某些分布条件下,在提供相当准确的聚合结果的同时降低了计算资源的使用。
11)自适应连接算法(Adaptive Join Algorithm)
ClickHouse支持自定义JOIN多个表,它更倾向于散列连接算法,如果有多个大表,则使用合并-连接算法
12)支持数据复制和数据完整性
ClickHouse使用异步的多主复制技术。当数据被写入任何一个可用副本后,系统会在后台将数据分发给其他副本,以保证系统在不同副本上保持相同的数据。在大多数情况下ClickHouse能在故障后自动恢复,在一些少数的复杂情况下需要手动恢复。
13)自身的限制
1、没有完整的事务支持。
2、缺少高频率,低延迟的修改或删除已存在数据的能力。仅能用于批量删除或修改数据,但这符合 GDPR。
3、稀疏索引使得ClickHouse不适合通过其键检索单行的点查询。
性能
ClickHouse表现出了比同类可比较产品更优的性能。你可以在 这里 查看具体的测试结果。
如下我截取一张和mysql的对比图:1)单个大查询吞吐量
吞吐量可以使用每秒处理的行数或每秒处理的字节数来衡量。
如果数据被放置在page cache中,则一个不太复杂的查询在单个服务器上大约能够以2-10GB/s(未压缩)的速度进行处理(对于简单的查询,速度可以达到30GB/s)。
如果数据没有在page cache中的话,那么速度将取决于你的磁盘系统和数据的压缩率。
例如,如果一个磁盘允许以400MB/s的速度读取数据,并且数据压缩率是3,则数据的处理速度为1.2GB/s。这意味着,如果你是在提取一个10字节的列,那么它的处理速度大约是1-2亿行每秒。
对于分布式处理,处理速度几乎是线性扩展的,但这受限于聚合或排序的结果不是那么大的情况下。
2)处理短查询的延迟时间
如果一个查询使用主键并且没有太多行(几十万)进行处理,并且没有查询太多的列,那么在数据被page cache缓存的情况下,它的延迟应该小于50毫秒(在最佳的情况下应该小于10毫秒)。
否则,延迟取决于数据的查找次数。如果你当前使用的是HDD(机械硬盘),在数据没有加载的情况下,查询所需要的延迟可以通过以下公式计算得知: 查找时间(10 ms) * 查询的列的数量 * 查询的数据块的数量。
3)处理大量短查询的吞吐量
在相同的情况下,ClickHouse可以在单个服务器上每秒处理数百个查询(在最佳的情况下最多可以处理数千个)。但是由于这不适用于分析型场景。因此我们建议每秒最多查询100次。
4)数据的写入性能
我们建议每次写入不少于1000行的批量写入,或每秒不超过一个写入请求。
当使用tab-separated格式将一份数据写入到MergeTree表中时,写入速度大约为50到200MB/s。如果您写入的数据每行为1Kb,那么写入的速度为50000到200000行每秒。如果您的行更小,那么写入速度将更高。
为了提高写入性能,您可以使用多个INSERT进行并行写入,这将带来线性的性能提升。