以下实例我们都以clickhouse最常用的(合并树)子类引擎来做介绍。
以分布式表为例,那么ck数据存放于该集群下多个shard分片中。如果shard不在一个节点上,也就是数据会分散到多台机下。每个分片中的数据会根据建表时指定的partition在进行划分,而单个partition中,如果数据容量超过一定阈值又会重新拆分。
clickhouse是真正的列式数据库管理系统,除了数据本身外基本不存在其他额外的数据。
下面我们看下clickhouse特有的计算优势。
- 多服务器分布式处理
在ClickHouse中,数据可以保存在不同的shard上,每一个shard都由一组用于容错的replica组成,查询可以多服务器并行地在所有shard上进行处理。 - 向量引擎
为了高效的使用CPU,计算时ck能按向量(列的一部分)进行处理,相对于实际的数据处理成本,向量化处理具有更低的转发成本。这样可以更加高效地使用CPU。
Clickhouse 中最强大的表引擎当属 MergeTree (合并树)引擎及该系列(*MergeTree)中的其他引擎。MergeTree 引擎系列的基本理念如下。当你有巨量数据要插入到表中,你要高效地一批批写入数据片段,并希望这些数据片段在后台按照一定规则合并。相比在插入时不断修改(重写)数据进存储,这种策略会高效很多。主要优势:
- 存储的数据按主键排序。
这让你可以创建一个用于快速检索数据的小稀疏索引。 - 允许使用分区,如果指定了 分区键 的话。
在相同数据集和相同结果集的情况下 ClickHouse 中某些带分区的操作会比普通操作更快。查询中指定了分区键时 ClickHouse 会自动截取分区数据。这也有效增加了查询性能。 - 支持数据副本。
ReplicatedMergeTree 系列的表便是用于此。
以官网用例来看。我们以 (CounterID, Date) 以主键。排序好的索引的图示会是下面这样:
如果指定查询如下:
,服务器会读取标记号在 [0, 3) 和 [6, 8) 区间中的数据。
,服务器会读取标记号在 [1, 3) 和 [7, 8) 区间中的数据。
,服务器会读取标记号在 [1, 10] 区间中的数据。上面例子可以看出使用索引通常会比全表描述要高效。
稀疏索引会引起额外的数据读取。当读取主键单个区间范围的数据时,每个数据块中最多会多读 行额外的数据。大部分情况下,当 时,ClickHouse的性能并不会降级。
稀疏索引让你能操作有巨量行的表。因为这些索引是常驻内存(RAM)的。ClickHouse 不要求主键惟一。所以,你可以插入多条具有相同主键的行。下面看在实际语法:
- ENGINE - 引擎名和参数。
ENGINE = MergeTree(). MergeTree 引擎没有参数。 - PARTITION BY — 分区键 。
要按月分区,可以使用表达式 toYYYYMM(date_column) ,这里的 date_column 是一个 Date 类型的列。这里该分区名格式会是 “YYYYMM” 这样。 - ORDER BY — 表的排序键。
可以是一组列的元组或任意的表达式。 例如: ORDER BY (CounterID, EventDate) 。 - PRIMARY KEY - 主键,如果要设成 跟排序键不相同。
默认情况下主键跟排序键(由 ORDER BY 子句指定)相同。因此,大部分情况下不需要再专门指定一个 PRIMARY KEY 子句。
存储部分相关大部分逻辑放在/src/Storages下。
表的顶层抽象是IStorage,对此接口不同的实现成为不同的表引擎. 例如 StorageMergeTree, StorageMemory等,这些类的实例是表。
该接口中包含很多通用的方法,常用的增删改查read、write、alter、drop等
- read
表的readStreams方法能够返回多个IBlockInputStream 对象允许并行处理数据. 这些多个数据块输入流能够从一个表中并行读取数据. 然后你能够用不同的转换来封装这些数据流(例如表达式评估,数据过滤) 能够被单独计算。
- write
- 数据块流
用于处理数据。我们使用数据块的数据流从某处读取数据,执行数据转换或者写入数据到某处。IBlockInputStream 有一个read方法获取下一个数据块。IBlockOutputStream 有一个write方法发送数据块到某处。
例如,当你从AggregatingBlockInputStream拉取数据时,它将从数据源上读取所有的数据,聚合它,然后为你返回一个汇总数据流。另一个示例:UnionBlockInputStream接收很多输入数据源和一些线程。它启动了多个线程,从多个数据源中并行读取数据。 - 数据块
是一个容器,代表了内存中一个表的子集。它也是三元组的集合:(IColumn,IDataType,columnname)
高可用存储对应生产来说是必不可少的。这里看下ck的分布式存储,和hive的区别还是较大,首先是在查询上需要借助分布式表才能实现。值得注意的是,ck的分布式表并不直接存储数据,而是类似于视图的存在。读是自动并行的。读取时,远程服务器表的索引(如果有的话)会被使用。
假设4个节点example01-01-1、example01-01-2、example01-02-1、example01-02-2。集群名称为logs。
我们在logs集群4个节点中都创建test1表,根据totalDate分区。
之后在集群中创建分布式表test1_all
然后可以向分布式表写入些测试数据,之后到具体的节点查原表进行校验。因为系列六中有类似的实例就不在此赘述。
ck推荐采用复制表+内部同步实现。我们先看下上述配置中属性。当设置false时,插入到分布式表中的数据被插入到两个本地表中,因为不会检查副本的一致性,并且随着时间的推移,副本数据可能会有些不一样。
复制表 ,ck数据副本是提供的表级的,而非服务器级别的,所以,服务器里可以同时有复制表和非复制表。这又是ck和hive的一个很大不同。
下面我们来看下四种复制模式
- 非复制表,internal_replication=false
如果在插入期间没有问题,则两个本地表上的数据保持同步。我们称之为“穷人的复制”,因为复制在网络出现问题的情况下容易发生分歧,没有一个简单的方法来确定哪一个是正确的复制。 - 非复制表,internal_replication=true
数据只被插入到一个本地表中,但没有任何机制可以将它转移到另一个表中。因此,在不同主机上的本地表看到了不同的数据,查询分布式表时会出现非预期的数据。 显然,这是配置ClickHouse集群的一种不正确的方法。 - 复制表,internal_replication=true 本文地址:http://lianchengexpo.xrbh.cn/quote/12803.html 迅博思语资讯 http://lianchengexpo.xrbh.cn/ , 查看更多