Clickhouse概览(一)

什么是clickhouse

ClickHouse是一个面向列的数据库管理系统(DBMS),用于联机分析处理查询(OLAP)

在“普通”面向行的数据库管理系统中,数据按以下顺序存储:

Clickhouse概览(一)_第1张图片
换句话说,与一行相关的所有值在物理上紧挨着存储。

面向行的 DBMS 的例子有 MySQL、 Postgres 和 MS SQL Server。

在列式数据库中,数据是这样存储的:
Clickhouse概览(一)_第2张图片
这些示例仅显示数据的排列顺序。来自不同列的值分别存储,并且来自同一列的数据一起存储。

面向列的DBMS的示例: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 场景的主要特性

  • List item

  • 绝大多数请求是为了读访问。

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

  • 数据被添加到 DB,但是不会被修改。

  • 对于读操作,从 DB 中提取了相当多的行,但只提取了列的一小部分。

  • 表是“宽”的,意思是它们包含大量的列。

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

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

  • 列值相当小: 数字和短字符串(例如,每个 URL 60字节)。

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

  • 事务不是必须的。

  • 数据一致性要求低。

  • 每个查询有一个大表。除一个表外,所有表都很小。

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

显而易见,OLAP 场景与其他流行场景(如 OLTP 或 Key-Value 访问)有很大的不同。 因此,如果您希望获得良好的性能,那么尝试使用 OLTP 或 Key-Value DB 来处理分析查询是没有意义的。 例如,如果您尝试使用 MongoDB 或 Redis 进行分析,那么与 OLAP 数据库相比,您的性能将非常差。

为什么面向列的数据库在OLAP方案中工作得更好

面向列的数据库更适合OLAP场景:它们在处理大多数查询时至少快100倍。下面将详细说明原因,但这一事实更易于直观地演示:

行数据库:
Clickhouse概览(一)_第3张图片
列数据库:

看到区别了吗?

输入和输出

  1. 对于分析查询,只需要读取少量的表列。在面向列的数据库中,您可以只读取所需的数据。例如,如果您需要100列中的5列,则可以预期I/O将减少20倍。

  2. 由于数据是以数据包的形式读取的,因此更容易压缩。列中的数据也更容易压缩。这进一步减少了I/O容量。

  3. 由于减少了I/O,系统缓存中可以容纳更多的数据。

例如,查询 “计算每个广告平台的记录数”,要求读取一个“广告平台ID”列,该列占用1个字节的未压缩字节。 如果大多数流量不是来自广告平台,则可以预期此列至少压缩10倍。 当使用快速压缩算法时,数据解压缩可能以每秒至少数GB的未压缩数据的速度进行。 换句话说,可以在单个服务器上以每秒约数十亿行的速度处理此查询。 该速度实际上是在实践中实现的。

$ clickhouse-client
ClickHouse client version 0.0.52053.
Connecting to localhost:9000.
Connected to ClickHouse server version 0.0.52053.
SELECT CounterID, count() FROM hits GROUP BY CounterID ORDER BY count() DESC LIMIT 20
┌─CounterID─┬──count()─┐
│    11420856057344 │
│    11508051619590 │
│      322844658301 │
│     3823042045932 │
│    14526342042158 │
│     9124438297270 │
│    15413926647572 │
│    15074824112755 │
│    24223221302571 │
│    33815813507087 │
│     6218012229491 │
│     8226412187441 │
│    23226112148031 │
│    14627211438516 │
│    16877711403636 │
│   412007211227824 │
│  1093880810519739 │
│     740889047015 │
│    1150798837972 │
│    3372348205961 │
└───────────┴──────────┘

CPU

由于执行查询需要处理大量的行,因此有助于为整个向量而不是单独的行调度所有操作,或者有助于实现查询引擎,从而几乎没有调度成本。 如果您不这样做,则对于任何半好的磁盘子系统,查询解释器都将不可避免地使CPU停顿。 将数据存储在列中并在可能时按列进行处理是有意义的。
有两种方法:

  1. 矢量引擎。所有操作都是为向量编写的,而不是为单独的值编写的。这意味着您不需要经常调用操作,而且调度成本可以忽略不计。操作代码包含优化的内部循环。

  2. 代码生成。为查询生成的代码中包含所有间接调用。

当然,这不是在“普通”数据库中完成的,因为在运行简单查询时这种引擎没有意义。不过,也有例外。例如,MemSQL使用代码生成来减少处理SQL查询时的延迟。(为了进行比较,分析型数据库管理系统需要优化吞吐量,而不是延迟。)

请注意,为了提高CPU效率,查询语言必须是声明性的(SQL或MDX),或者至少是向量(J,K)。

你可能感兴趣的:(大数据)