ClickHouse概述

简介

ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。
列式数据库总是将同一列的数据存储在一起,不同列的数据也总是分开存储。

支持的特性

  • 真正的列式数据库管理系统
  • 数据压缩
  • 数据的磁盘存储
  • 多核心并行处理
  • 多服务器分布式处理:数据可以保存在不同的shard上,每一个shard都由一组用于容错的replica组成,查询可以并行的在所有shard上进行处理。
  • 支持SQL
  • 向量引擎: 为了高效的使用CPU,数据不仅仅按列存储,同时还按向量(列的一部分)进行处理。
  • 实时的数据更新
  • 索引
  • 适合在线查询
  • 支持近似计算
  • 支持数据复制和数据完整性: ClickHouse使用异步的多主复制技术。当数据被写入任何一个可用副本后,系统会在后台将数据分发给其他副本,以保证系统在不同副本上保持相同的数据。在大多数情况下ClickHouse能在故障后自动恢复,在一些复杂的情况下需要少量的手动恢复。

不支持的特性

  • 没有完整的事物支持。
  • 缺少高频率,低延迟的修改或删除已存在数据的能力。
  • 稀疏索引使得ClickHouse不适合通过其键检索单行的点查询。

性能

  • 读性能: 如果数据被放置在page cache中,则一个不太复杂的查询在单个服务器上大约能够以2-10GB/s(未压缩)的速度进行处理(对于简单的查询,速度可以达到30GB/s)。如果数据没有在page cache中的话,那么速度将取决于你的磁盘系统和数据的压缩率。例如,如果一个磁盘允许以x MB/s的速度读取数据,并且数据压缩率是y,则数据的处理速度为x * y MB/s。
  • 延迟: 在数据被page cache缓存的情况下,一个查询的延迟应该小于50毫秒(在最佳的情况下应该小于10毫秒)。 否则,延迟取决于数据的查找次数。查询所需要的延迟可以通过以下公式计算得知: 查找时间(10 ms) * 查询的列的数量 * 查询的数据块的数量。
  • 写性能:我们建议每次写入不少于1000行的批量写入,或每秒不超过一个写入请求。当使用tab-separated格式将一份数据写入到MergeTree表中时,写入速度大约为50到200MB/s。为了提高写入性能,可以使用多个INSERT进行并行写入,这将带来线性的性能提升。

架构

ClickHouse是一个完全面向列式的分布式数据库。数据通过列存储,在查询过程中,数据通过数组来处理(向量或者列Chunk)。当进行查询时,操作被转发到数组上,而不是在特定的值上。因此被称为”向量化查询执行”,相对于实际的数据处理成本,向量化处理具有更低的转发成本。

  • Columns(列):为了表示内存中的列(列的 chunks),IColumn将被使用。这个接口提供了一些辅助方法来实现不同的关系操作符。几乎所有的操作符都是非更改的:他们不能更改原有的列,但是创建一个新的更新的列。不同的IColumn实现(ColumnUInt8,ColumnString等)负责列的内存布局。内存布局通常是一个连续的数组。
  • Data Types(数据类型):IDataType 负责序列化和反序列化: 读写这个列的值或者以二进制或文本的方式的值.IDataType 直接与表中的数据类型一致。IDataType 仅存储元数据。
  • Block(数据块):一个数据块是一个容器,代表了内存中一个表的子集。它也是三元组的集合:(IColumn,IDataType,columnname). 在查询执行过程中, 数据通过数据块来处理. 如果你有一个数据块, 我们有数据(在IColumn对象中), 我们有这个数据的类型(在IDataType中) 告诉我们怎样处理此列,同时我们有此列名称。
  • Block Streams(数据块流):数据块流用于处理数据。我们使用数据块的数据流从某处读取数据,执行数据转换或者写入数据到某处。IBlockInputStream 有一个read方法获取下一个数据块。IBlockOutputStream 有一个write方法发送数据块到某处。
  • I/O:对于面向字节的输入/输出。有 ReadBuffer 和 WriteBuffer 抽象类。
  • Tables:表通过IStorage接口来表示。对此接口不同的实现成为不同的表引擎。最重要的IStorage 方法是读和写操。
  • Functions:普通函数并不能改变行的数量 – 他们单独处理每个行。事实上,对于每个行,函数不能被调用,但是对于数据块的数据可实现向量化查询执行。
  • Aggregate Functions:聚合函数是状态函数。 他们积累传递的值到某个状态, 允许你从这个状态获得结果。他们用IAggregateFunction来管理。

数据副本

  • 只有 MergeTree 系列里的表可支持副本。
  • 副本是表级别的,不是整个服务器级的。所以,服务器里可以同时有复制表和非复制表。
  • 副本不依赖分片。每个分片有它自己的独立副本。
  • 对于 INSERT 和 ALTER 语句操作数据的会在压缩的情况下被复制。而 CREATE,DROP,ATTACH,DETACH 和 RENAME 语句只会在单个服务器上执行,不会被复制。
  • 要使用副本,需在配置文件中设置 ZooKeeper 集群的地址。如果配置文件中没有设置 ZooKeeper ,则无法创建复制表,并且任何现有的复制表都将变为只读。
  • 复制是多主异步。 INSERT 语句(以及 ALTER )可以发给任意可用的服务器。数据会先插入到执行该语句的服务器上,然后被复制到其他服务器。由于它是异步的,在其他副本上最近插入的数据会有一些延迟。如果部分副本不可用,则数据在其可用时再写入。
  • 默认情况下,INSERT 语句仅等待一个副本写入成功后返回。如果数据只成功写入一个副本后该副本所在的服务器不再存在,则存储的数据会丢失。要启用数据写入多个副本才确认返回,使用 insert_quorum 选项。
  • 单个数据块写入是原子的。 INSERT 的数据按每块最多 max_insert_block_size = 1048576 行进行分块。
  • 数据块会去重。对于被多次写的相同数据块(大小相同且具有相同顺序的相同行的数据块),该块仅会写入一次。这样设计的原因是万一在网络故障时客户端应用程序不知道数据是否成功写入DB,此时可以简单地重复 INSERT 。把相同的数据发送给多个副本 INSERT 并不会有问题。因为这些 INSERT 是完全相同的(会被去重)。
  • 你可以给数据做任意多的副本。系统会监视副本数据同步情况,并能在发生故障后恢复。

创建复制表

  • 在表引擎名称上加上 Replicated 前缀就可以创建复制表。例如:ReplicatedMergeTree。
  • 要删除副本,使用 DROP TABLE。但它只删除那个位于运行该语句的服务器上的副本。
  • 在每个副本服务器上运行 CREATE TABLE 查询。将创建新的复制表,或给现有表添加新副本。如果其他副本上已包含了某些数据,在表上添加新副本,则在运行语句后,数据会从其他副本复制到新副本。换句话说,新副本会与其他副本同步。

故障恢复

  • 如果服务器启动时 ZooKeeper 不可用,则复制表会切换为只读模式。系统会定期尝试去连接 ZooKeeper。
  • 如果在 INSERT 期间 ZooKeeper 不可用,或者在与 ZooKeeper 交互时发生错误,则抛出异常。
  • 连接到 ZooKeeper 后,系统会检查本地文件系统中的数据集是否与预期的数据集( ZooKeeper 存储此信息)一致。如果存在轻微的不一致,系统会通过与副本同步数据来解决。
  • 如果系统检测到损坏的数据片段(文件大小错误)或无法识别的片段(写入文件系统但未记录在 ZooKeeper 中的部分),则会把它们移动到 'detached' 子目录(不会删除)。而副本中其他任何缺少的但正常数据片段都会被复制同步。
  • 如果本地数据集与预期数据的差异太大,则会触发安全机制。服务器在日志中记录此内容并拒绝启动。在这种情况下,数据恢复则是半自动模式,通过用户主动操作触发。

表分区

MergeTree系列的表(包括可复制表)可以使用分区。基于 MergeTree 表的物化视图也支持分区。
一个分区是指按指定规则逻辑组合一起的表的记录集。可以按任意标准进行分区,如按月,按日或按事件类型。为了减少需要操作的数据,每个分区都是分开存储的。访问数据时,ClickHouse 尽量使用这些分区的最小子集。
分区是在建表的 PARTITION BY expr 子句中指定。分区键可以是关于列的任何表达式。例如,指定按月分区,表达式为 toYYYYMM(date_column)
新数据插入到表中时,这些数据会存储为按主键排序的新片段(块)。插入后 10-15 分钟,同一分区的各个片段会合并为一整个片段。
注意 那些有相同分区表达式值的数据片段才会合并。
可以通过系统表system.parts表查看表片段和分区信息。

#查看visits表的表片段和分区信息
SELECT 
    partition,
    name, 
    active
FROM system.parts 
WHERE table = 'visits'

partition 列存储分区的名称
name 列为分区中数据片段的名称。
active 列为片段状态。1 激活状态;0 非激活状态。非激活片段是那些在合并到较大片段之后剩余的源数据片段。损坏的数据片段也表示为非活动状态。
ClickHouse 大约在插入后15分钟定期报告合并操作,合并插入的数据片段。此外,你也可以使用OPTIMIZE语句直接执行合并。

OPTIMIZE TABLE visits PARTITION 201902;

非激活片段会在合并后的10分钟左右删除。
查看片段和分区信息的另一种方法是进入表的目录:/var/lib/clickhouse/data//

/。

表索引

你可能感兴趣的:(ClickHouse概述)