什么是ClickHouse?
cookqq ›博客列表 ›列式数据库

什么是ClickHouse?

2024-02-23 11:02:50.0|分类: 列式数据库|浏览量: 745

摘要: ClickHouse支持在表中定义主键。为了使查询能够快速在主键中进行范围查找,数据总是以增量的方式有序的存储在MergeTree中。因此,数据可以持续不断地高效的写入到表中,并且写入的过程中不会存在任何加锁的行为。

ClickHouse是俄罗斯的搜索巨头Yandex公司开发的面向列式存储的关系型数据库(DBMS),

于2016年开源,使用C++编写的,主要用于在线分析处理查询(OLAP),能够使用SQL查询实时生成分析数据报告。

ClickHouse 是过去两年中 OLAP 领域中最热门的。

ClickHouse的初始设计目的是为了服务于自己公司的一款名叫Yandex.Metrica的产品。

Metrica是一款Web流量分析工具,基于前方探针采集行为数据,然后进行一系列的数据分析,

类似数据仓库的OLAP分析。而在采集数据的过程中,一次页面click(点击),会产生一个event(事件)。

所以,整个系统的逻辑就是基于页面的点击事件流,面向数据仓库进行OLAP分析。

所以ClickHouse的全称是Click Stream(点击流),Data WareHouse(数据仓库),简称ClickHouse。


ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。

在传统的行式数据库系统中,数据按如下顺序存储:

RowWatchIDJavaEnableTitleGoodEventEventTime
#0893543506621Investor Relations12016-05-18 05:19:20
#1903295099580Contact us12016-05-18 08:10:20
#2899537060541Mission12016-05-18 07:38:00
#N……………

处于同一行中的数据总是被物理的存储在一起。

常见的行式数据库系统有:MySQL、Postgres和MS SQL Server。


在列式数据库系统中,数据按如下的顺序存储:

Row:#0#1#2#N
WatchID:893543506629032950995889953706054…
JavaEnable:101…
Title:Investor RelationsContact usMission…
GoodEvent:111…
EventTime:2016-05-18 05:19:202016-05-18 08:10:202016-05-18 07:38:00…

这些示例只显示了数据的排列顺序。来自不同列的值被单独存储,来自同一列的数据被存储在一起。


OLAP场景的关键特征

  • 绝大多数是读请求

  • 数据以相当大的批次(> 1000行)更新,而不是单行更新;或者根本没有更新。

  • 已添加到数据库的数据不能修改。

  • 对于读取,从数据库中提取相当多的行,但只提取列的一小部分。

  • 宽表,即每个表包含着大量的列

  • 查询相对较少(通常每台服务器每秒查询数百次或更少)

  • 对于简单查询,允许延迟大约50毫秒

  • 列中的数据相对较小:数字和短字符串(例如,每个URL 60个字节)

  • 处理单个查询时需要高吞吐量(每台服务器每秒可达数十亿行)

  • 事务不是必须的

  • 对数据一致性要求低

  • 每个查询有一个大表。除了他以外,其他的都很小。

  • 查询结果明显小于源数据。换句话说,数据经过过滤或聚合,因此结果适合于单个服务器的RAM中


输入/输出

  1. 针对分析类查询,通常只需要读取表的一小部分列。在列式数据库中你可以只读取你需要的数据。例如,如果只需要读取100列中的5列,这将帮助你最少减少20倍的I/O消耗。

  2. 由于数据总是打包成批量读取的,所以压缩是非常容易的。同时数据按列分别存储这也更容易压缩。这进一步降低了I/O的体积。

  3. 由于I/O的降低,这将帮助更多的数据被系统缓存。

CPU

由于执行一个查询需要处理大量的行,因此在整个向量上执行所有操作将比在每一行上执行所有操作更加高效。同时这将有助于实现一个几乎没有调用成本的查询引擎。如果你不这样做,使用任何一个机械硬盘,查询引擎都不可避免的停止CPU进行等待。所以,在数据按列存储并且按列执行是很有意义的。

数据压缩

在一些列式数据库管理系统中(例如:InfiniDB CE 和 MonetDB) 并没有使用数据压缩。但是, 若想达到比较优异的性能,数据压缩确实起到了至关重要的作用。

除了在磁盘空间和CPU消耗之间进行不同权衡的高效通用压缩编解码器之外,ClickHouse还提供针对特定类型数据的专用编解码器,这使得ClickHouse能够与更小的数据库(如时间序列数据库)竞争并超越它们。

多服务器分布式处理

上面提到的列式数据库管理系统中,几乎没有一个支持分布式的查询处理。 在ClickHouse中,数据可以保存在不同的shard上,每一个shard都由一组用于容错的replica组成,查询可以并行地在所有shard上进行处理。这些对用户来说是透明的

向量引擎

为了高效的使用CPU,数据不仅仅按列存储,同时还按向量(列的一部分)进行处理,这样可以更加高效地使用CPU。

索引

按照主键对数据进行排序,这将帮助ClickHouse在几十毫秒以内完成对数据特定值或范围的查找。

稠密索引:一条数据创建一条索引

稀疏索引:一段数据创建一条索引


一级索引是稀疏索引,意思就是说:每一段数据生成一条索引记录,而不是每一条数据都生成索引,

 如果是每一条数据都生成索引,则是稠密索引。用一个形象的例子来说明:如果把MergeTree比作一本书,

那么稀疏索引就好比是这本书的一级章节目录。一级章节目录不会具体对应到每个字的位置,

只会记录每个章节的起始页码。

MergeTree 的主键使用 PRIMARY KEY 定义,待主键定义之后,MergeTree 会依据 index_granularity 间隔

(默认 8192 行),为数据表生成一级索引并保存至 primary.idx 文件内。


支持数据复制和数据完整性

ClickHouse使用异步的多主复制技术。当数据被写入任何一个可用副本后,系统会在后台将数据分发给其他副本,以保证系统在不同副本上保持相同的数据。在大多数情况下ClickHouse能在故障后自动恢复,在一些少数的复杂情况下需要手动恢复。


限制

  1. 没有完整的事务支持。

  2. 缺少高频率,低延迟的修改或删除已存在数据的能力。仅能用于批量删除或修改数据,但这符合 GDPR。

  3. 稀疏索引使得ClickHouse不适合通过其键检索单行的点查询。

  4. 不擅长 join 操作;

  5. 不支持高并发,官方建议qps为100。原因: ClickHouse 将数据划分为多个 partition,每个 partition 再进一步划分为多个 index_granularity(索引粒度),然后通过多个 CPU核心分别处理其中的一部分来实现并行数据处理。在这种设计下, 单条 Query 就能利用整机所有 CPU。 极致的并行处理能力,极大的降低了查询延时。所以,ClickHouse 即使对于大量数据的查询也能够化整为零平行处理。但是有一个弊端就是对于单条查询使用多 cpu,就不利于同时并发多条查询。所以对于高 qps 的查询业务, ClickHouse 并不是强项。

  6. 缺少高频率,低延迟的修改或删除已存在数据的能力。仅能用于批量删除或修改数据;

  7. 不支持分词查询;

单个大查询的吞吐量

吞吐量可以使用每秒处理的行数或每秒处理的字节数来衡量。如果数据被放置在page cache中,则一个不太复杂的查询在单个服务器上大约能够以2-10GB/s(未压缩)的速度进行处理(对于简单的查询,速度可以达到30GB/s)。如果数据没有在page cache中的话,那么速度将取决于你的磁盘系统和数据的压缩率。例如,如果一个磁盘允许以400MB/s的速度读取数据,并且数据压缩率是3,则数据的处理速度为1.2GB/s。这意味着,如果你是在提取一个10字节的列,那么它的处理速度大约是1-2亿行每秒。

处理短查询的延迟时间

如果一个查询使用主键并且没有太多行(几十万)进行处理,并且没有查询太多的列,那么在数据被page cache缓存的情况下,它的延迟应该小于50毫秒(在最佳的情况下应该小于10毫秒)。 否则,延迟取决于数据的查找次数。如果你当前使用的是HDD,在数据没有加载的情况下,查询所需要的延迟可以通过以下公式计算得知: 查找时间(10 ms) * 查询的列的数量 * 查询的数据块的数量。

处理大量短查询的吞吐量

在相同的情况下,ClickHouse可以在单个服务器上每秒处理数百个查询(在最佳的情况下最多可以处理数千个)。但是由于这不适用于分析型场景。因此我们建议每秒最多查询100次。

为什么是100,不支持高并发?

ClickHouse快是因为采用了并行处理机制,即使一个查询,也会用服务器一半的CPU去执行,所以ClickHouse不能支持高并发的使用场景,默认单查询使用CPU核数为服务器核数的一半,安装时会自动识别服务器核数,可以通过配置文件修改该参数。

为什么要使用一半的CPU呢?

clickhouse每次数据写入都会生成一个新的分区版本,clickhouse异步合并分区数据,时间官网说是10分钟-15分钟。

在clickhouse中数据被分成了多个分区,查询某条数据时通过多分区的数据,利用CPU的多核同时并行处理获取数据,降低了查询时长;

数据的写入性能

我们建议每次写入不少于1000行的批量写入,或每秒不超过一个写入请求。当使用tab-separated格式将一份数据写入到MergeTree表中时,写入速度大约为50到200MB/s。如果您写入的数据每行为1Kb,那么写入的速度为50,000到200,000行每秒。如果您的行更小,那么写入速度将更高。为了提高写入性能,您可以使用多个INSERT进行并行写入,这将带来线性的性能提升。

为什么写入性能这么好?

ClickHouse中的MergeTree也是类LSM树的思想,日志结构合并树,但不是树,而是利用磁盘顺序读写能力,

实现一个多层读写的存储结构 是一种分层,有序,面向磁盘的数据结构,核心思想是利用了磁盘批量的顺序写要远比

随机写性能高出很多 大大提升了数据的写入能力。

充分利用了磁盘顺序写的特性,实现高吞吐写能力,数据写入后定期在后台Compaction。

在数据导入时全部是顺序append写,在后台合并时也是多个段merge sort后顺序写回磁盘。

聚合与非聚合数据

有一种流行的观点认为,想要有效的计算统计数据,必须要聚合数据,因为聚合将降低数据量。

但是数据聚合是一个有诸多限制的解决方案,例如:

  • 你必须提前知道用户定义的报表的字段列表

  • 用户无法自定义报表

  • 当聚合条件过多时,可能不会减少数据,聚合是无用的。

  • 存在大量报表时,有太多的聚合变化(组合爆炸)

  • 当聚合条件有非常大的基数时(如:url),数据量没有太大减少(少于两倍)

  • 聚合的数据量可能会增长而不是收缩

  • 用户不会查看我们为他生成的所有报告,大部分计算将是无用的

  • 各种聚合可能违背了数据的逻辑完整性

如果我们直接使用非聚合数据而不进行任何聚合时,我们的计算量可能是减少的。


为什么查询这么快

利用存储引擎的特殊设计充分减少磁盘I/O对查询速度的影响。从用户提交一条SQL语句进行查询到最终输出结果的过程中,大量的时间是消耗在了磁盘I/O上,在很多情况下,I/O所占用的时间可以达到整个时间的90%以上。对存储引擎磁盘I/O的优化可以获得非常大的收益。ClickHouse的存储引擎设计中大量优化的目的也是为了减少磁盘I/O。


参考文档:

https://www.toutiao.com/article/7256596641862566463/?channel=&source=search_tab

一键分享文章

分类列表

  • • struts源码分析
  • • flink
  • • struts
  • • redis
  • • kafka
  • • ubuntu
  • • zookeeper
  • • hadoop
  • • activiti
  • • linux
  • • 成长
  • • NIO
  • • 关键词提取
  • • mysql
  • • android studio
  • • zabbix
  • • 云计算
  • • mahout
  • • jmeter
  • • hive
  • • ActiveMQ
  • • lucene
  • • MongoDB
  • • netty
  • • flume
  • • 我遇到的问题
  • • GRUB
  • • nginx
  • • 大家好的文章
  • • android
  • • tomcat
  • • Python
  • • luke
  • • android源码编译
  • • 安全
  • • MPAndroidChart
  • • swing
  • • POI
  • • powerdesigner
  • • jquery
  • • html
  • • java
  • • eclipse
  • • shell
  • • jvm
  • • highcharts
  • • 设计模式
  • • 列式数据库
  • • spring cloud
  • • docker+node.js+zookeeper构建微服务
版权所有 cookqq 感谢访问 支持开源 京ICP备15030920号
CopyRight 2015-2018 cookqq.com All Right Reserved.