本⽂就对ClickHouse的复制表、分布式表机制和⽤法作个介绍。
Replicated Table & ReplicatedMergeTree Engines
ClickHouse的副本机制之所以叫“复制表”,是因为它⼯作在表级别,⽽不是集级别(如HDFS)。也就是说,⽤户在创建表时可以通过指定引擎选择该表是否⾼可⽤,每张表的分⽚与副本都是互相独⽴的。
⽬前⽀持复制表的引擎是ReplicatedMergeTree引擎族,它与平时最常⽤的MergeTree引擎族是正交的,如下图所⽰。
下⾯给出ReplicatedMergeTree引擎的完整建表DDL语句。
CREATE TABLE IF NOT EXISTS test.events_local ON CLUSTER '{cluster}' (
ts_date Date,
ts_date_time DateTime,
user_id Int64,
event_type String,
site_id Int64,
groupon_id Int64,
category_id Int64,
merchandise_id Int64,
search_text String
-- A lot
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/test/events_local','{replica}')
PARTITION BY ts_date
ORDER BY (ts_date,toStartOfHour(ts_date_time),site_id,event_type)
SETTINGS index_granularity = 8192;
其中,ON CLUSTER语法表⽰分布式DDL,即执⾏⼀次就可在集所有实例上创建同样的本地表。集标识符{cluster}、分⽚标识
符{shard}和副本标识符{replica}来⾃之前提到过的复制表宏配置,即l中<macros>⼀节的内容,配合ON CLUSTER语法⼀同使⽤,可以避免建表时在每个实例上反复修改这些值。
ReplicatedMergeTree引擎族接收两个参数:
ZK中该表相关数据的存储路径,ClickHouse官⽅建议规范化,如上⾯的格
式/clickhouse/tables/{shard}/[database_name]/[table_name]。
副本名称,⼀般⽤{replica}即可。
观察⼀下上述ZK路径下的znode结构与内容。
[zk: localhost:2181(CONNECTED) 0] ls /clickhouse/tables/01/test/events_local
[metadata, temp, mutations, log, leader_election, columns, blocks, nonincrement_block_numbers, replicas, quorum, block_numbers]
[zk: localhost:2181(CONNECTED) 1] get /clickhouse/tables/04/test/events_local/columns
columns format version: 1
9 columns:
`ts_date` Date
`ts_date_time` DateTime
`user_id` Int64
`event_type` String
`site_id` Int64
`groupon_id` Int64
`category_id` Int64
`merchandise_id` Int64
`search_text` String
# ...................
[zk: localhost:2181(CONNECTED) 2] get /clickhouse/tables/07/test/events_local/metadata
metadata format version: 1
date column:
sampling expression:
index granularity: 8192
mode: 0
sign column:
primary key: ts_date, toStartOfHour(ts_date_time), site_id, event_type
data format version: 1
partition key: ts_date
granularity bytes: 10485760
# ...................
Distributed Table & Distributed Engine
ClickHouse分布式表的本质并不是⼀张表,⽽是⼀些本地物理表(分⽚)的分布式视图,本⾝并不存储数据。⽀持分布式表的引擎是Distributed,建表DDL语句⽰例如下,_all只是分布式表名⽐较通⽤的后缀⽽已。
CREATE TABLE IF NOT EXISTS test.events_all ON CLUSTER sht_ck_cluster_1
⽽在写⼊时,我们有两种选择:⼀是写分布式表,⼆是写underlying的本地表。孰优孰劣呢?
直接写分布式表的优点⾃然是可以让ClickHouse控制数据到分⽚的路由,缺点就多⼀些:
数据是先写到⼀个分布式表的实例中并缓存起来,再逐渐分发到各个分⽚上去,实际是双写了数据(写⼊放⼤),浪费资源;
数据写⼊默认是异步的,短时间内可能造成不⼀致;
应⽤层路由并不是什么难事,所以如果条件允许,在⽣产环境中总是推荐写本地表、读分布式表。举个例⼦,在笔者最近引⼊的连接器中,就采⽤了随机路由,部分代码如下。
private Request buildRequest(ClickhouseRequestBlank requestBlank) {
String resultCSV = String.join(" , ", Values());
String query = String.format("INSERT INTO %s VALUES %s", TargetTable(), resultCSV);
String host = ClickhouseClusterSettings().getRandomHostUrl();
BoundRequestBuilder builder = asyncHttpClient
.preparePost(host)
.setHeader(HttpHeaders.Names.CONTENT_TYPE, "text/plain; charset=utf-8")
.setBody(query);
if (ClickhouseClusterSettings().isAuthorizationRequired()) {
builder.setHeader(HttpHeaders.Names.AUTHORIZATION, "Basic " + ClickhouseClusterSettings().getCredentials());        }
return builder.build();
}
public String getRandomHostUrl() {
currentHostId = ThreadLocalRandom.current().nextInt(hostsWithPorts.size());
(currentHostId);
}
exists的用法
The End
ClickHouse确实是⼀个设计很精妙的OLAP数据库,还有很多细节等着我们在实际应⽤中去发掘。
民那晚安晚安。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。