ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。它的表分为两种:一种是分布式表,一种是本地表:
- 分布式表:一个逻辑上的表,可理解为数据库中的view,一般查询都是分布式表,分布式表的引擎会将读请求路由到本地表进行查询,然后汇总输出。这里强调一点:分布式表本身不存储数据,它只是提供了一个可以分布式访问数据的框架。
- 本地表:实在存储数据的表
当然,ClickHouse还有其他形式的表,如
- 副本表:数据在ck集群上,每个分片有多个副本,在集群中,要保证高可用,数据就必须有冗余——即副本。
- 外部表:ck中只有元数据,数据在hdfs等外部存储介质中
在ck中,副本机制其实也称为『复制表』,这是因为它工作在表级别上,而不是集群级别(如HDFS),所以在同一个服务节点中,每张表的引擎选择是相互独立的,他们的分片与副本也是互相独立的。目前支持复制表的引擎是ReplicatedMergeTree引擎族。
下面谈谈数据的写入。
数据是直接写入本地表还是分布式表呢? 看了相关的文章,都是建议直接写本地表,如
Sharding key in Distributed table is used only at INSERT.
For SELECTs, sharding key does not make sense and Distributed tables always query all shards.Insertion to local tables is more efficient and more flexible than insertion to Distributed table.
It is more efficient because it avoids excessive copying of temporary data.
It is more flexible because you can use any sophisticated sharding schemas, not only simple sharding by modulo of division.Insertion to local tables require more logic on your client application and can be more difficult to use. But also it is conceptually more simple.
If your queries rely on some assumptions on data distribution, like queries that use IN or JOIN (joining co-located data) instead of GLOBAL IN, GLOBAL JOIN, then you have to maintain correctness by yourself.
正如上面的建议:
- 分布式表中的sharding key仅在insert中使用,对于查询sharding key是没有意义的,分布式表总要查询所有分片
- 插入本地表比插入分布式表更加有效、如灵活。
- 本地表可避免临时数据的过度复制
- 直接写某个节点的分布式表,需要建立N-1个连接(N是集群节点数)分发数据,导致连接数占用
- 当每个节点异常,分布式表分把写入的数据放到tmp目录,无限制的重试发送
- 分布式表的设计主要是读而不是写
当然插入数据量不大时,本地表与分布式表都可以。