确保本地PC的时间与集群的时间差要小于5分钟,若无法确定,请联系系统管理员。集 群的时间可通过FusionInsight Manager页面右下角查看。
操作场景
ClickHouse针对多个场景提供样例工程,帮助客户快速学习ClickHouse工程。
操作步骤
步骤1 参考通过开源镜像站获取样例工程,获取样例代码解压目录中“src”目录下的样例工 程文件夹“clickhouse-examples”以及Maven相关配置。
步骤2 在应用开发环境中,导入样例工程到IntelliJ IDEA开发环境。
1. 在IDEA界面选择“File > New > Project from Existing Sources”。
2. 在显示的“Select File or Directory to Import”对话框中,选择“clickhouse-examples”文件夹中的“pom.xml”文件,单击“OK”。
3. 确认后续配置,单击“Next”;如无特殊需求,使用默认值即可。
4. 选择推荐的JDK版本,单击“Finish”完成导入。
步骤3 工程导入完成后,修改样例工程的“conf”目录下的“clickhouse-example.properties”文件,根据实际环境信息修改相关参数。
loadBalancerIPList=
sslUsed=false
loadBalancerHttpPort=21425 loadBalancerHttpsPort=21426
CLICKHOUSE_SECURITY_ENABLED=true user=
password=
clusterName=default_cluster databaseName=testdb tableName=testtb batchRows=10000 batchNum=10
应用开发指南 8 ClickHouse 开发指南(普通模式)
表8-3 配置说明表
配置名称 默认值 含义
loadBalancerIPLis
t - 必填参数,配置为LoadBalance的IP列表。
登录Manager,选择“集群 > 服务 > ClickHouse
> 实例”,查看所有ClickHouseBalancer实例对应 的业务IP地址。
多个IP地址使用逗号分割,例如配置为
“10.10.10.100,10.10.10.101”。
sslUsed false 是否启用ssl加密,安全模式集群建议配置为
“true”。
loadBalancerHttp
Port 21425 LoadBalance的HTTP端口。
登录FusionInsight Manager,选择“集群 > 服务
> ClickHouse > 实例”,单击对应的
ClickHouseBalancer实例,选择“实例配置 > 全 部配置”,搜索“lb_http_port”并获取其参数 值,默认为21425。
loadBalancerHttp
sPort 21426 LoadBalance的HTTPS端口,若sslUsed配置为 true,则此参数不允许为空。
登录FusionInsight Manager,选择“集群 > 服务
> ClickHouse > 实例”,单击对应的
ClickHouseBalancer实例,选择“实例配置 > 全 部配置”,搜索“lb_https_port”并获取其参数 值,默认为21426。
CLICKHOUSE_SEC
URITY_ENABLED true ClickHouse安全模式开关,普通模式集群时该参数 填写为false。
databaseName testdb 样例代码工程中需要创建的数据库名称,可以根据 实际情况修改。
tableName testtb 样例代码工程中需要创建的表名称,可以根据实际 情况修改。
batchRows 10000 一个批次写入数据的条数。
batchNum 10 写入数据的总批次。
应用开发指南 8 ClickHouse 开发指南(普通模式)
说明
ClickHouse虽有集群能力,但没有统一的访问入口,客户端需要直接感知集群内所有的节点,易 用性不好。ClickHouse提供了基于Loadbalance部署架构,可以将用户访问流量自动分发到多台 后端节点,扩展系统对外的服务能力,实现更高水平的应用容错。客户端应用请求集群时,使用 基于Nginx的ClickHouseBalancer控制节点来进行流量分发,无论集群写入的负载、读的负载以 及应用接入的高可用性都具备了有力的保障。
----结束
8.3 开发程序
8.3.1 典型场景说明
通过典型场景,我们可以快速学习和掌握ClickHouse的开发过程,并且对关键的接口 函数有所了解。
8.3.2 开发思路
开发思路
ClickHouse作为一款独立的DBMS系统,使用SQL语言就可以进行常见的操作。开发程 序示例中,全部通过clickhouse-jdbc API接口来进行描述。
● 设置属性
● 建立连接
● 创建库
● 创建表
● 插入数据
● 查询数据
● 删除表
8.4 样例代码说明
8.4.1 设置属性
设置连接属性,如下样例代码设置socket超时时间为60s。
ClickHouseProperties clickHouseProperties = new ClickHouseProperties();
clickHouseProperties.setSocketTimeout(60000);
clickHouseProperties.setSsl(true);
clickHouseProperties.setSslMode("none");
8.4.2 建立连接
创建连接时传入表8-3中配置的user和password作为认证凭据,ClickHouse会带着用户 名和密码在服务端进行安全认证。
应用开发指南 8 ClickHouse 开发指南(普通模式)
ClickHouseDataSource clickHouseDataSource =new ClickHouseDataSource(JDBC_PREFIX + serverList.get(tries - 1), clickHouseProperties);
connection = clickHouseDataSource.getConnection(user, password);
8.4.3 创建库
通过on cluster语句在集群中创建表8-3中以databaseName参数值为数据库名的数据 库。private void createDatabase(String databaseName, String clusterName) throws Exception {
String createDbSql = "create database if not exists " + databaseName + " on cluster " + clusterName;
util.exeSql(createDbSql);
}
8.4.4 创建表
通过on cluster语句在集群中创建表8-3中tableName参数值为表名的ReplicatedMerge 表和Distributed表。
private void createTable(String databaseName, String tableName, String clusterName) throws Exception { String createSql = "create table " + databaseName + "." + tableName + " on cluster " + clusterName +
" (name String, age UInt8, date Date)engine=ReplicatedMergeTree('/clickhouse/tables/{shard}/" + databaseName + "." + tableName + "'," + "'{replica}') partition by toYYYYMM(date) order by age";
String createDisSql = "create table " + databaseName + "." + tableName + "_all" + " on cluster " + clusterName + " as " + databaseName + "." + tableName + " ENGINE = Distributed(default_cluster," + databaseName + "," + tableName + ", rand());"; ArrayList<String> sqlList = new ArrayList<String>();
sqlList.add(createSql);
sqlList.add(createDisSql);
util.exeSql(sqlList);
}
8.4.5 插入数据
创建表创建的表具有三个字段,分别是String、UInt8和Date类型。
String insertSql = "insert into " + databaseName + "." + tableName + " values (?,?,?)";
PreparedStatement preparedStatement = connection.prepareStatement(insertSql);
long allBatchBegin = System.currentTimeMillis();
for (int j = 0; j < batchNum; j++) { for (int i = 0; i < batchRows; i++) {
preparedStatement.setString(1, "huawei_" + (i + j * 10));
preparedStatement.setInt(2, ((int) (Math.random() * 100)));
preparedStatement.setDate(3, generateRandomDate("2018-01-01", "2021-12-31"));
preparedStatement.addBatch();
}
long begin = System.currentTimeMillis();
preparedStatement.executeBatch();
long end = System.currentTimeMillis();
log.info("Inert batch time is {} ms", end - begin);
}long allBatchEnd = System.currentTimeMillis();
log.info("Inert all batch time is {} ms", allBatchEnd - allBatchBegin);
8.4.6 查询数据
查询语句1:querySql1查询创建表创建的tableName表中任意10条数据;查询语句 2:querySql2通过内置函数对创建表创建的tableName表中的日期字段取年月后进行 聚合。
private void queryData(String databaseName, String tableName) throws Exception {
String querySql1 = "select * from " + databaseName + "." + tableName + "_all" + " order by age limit 10";
String querySql2 = "select toYYYYMM(date),count(1) from " + databaseName + "." + tableName + "_all"
+ " group by toYYYYMM(date) order by count(1) DESC limit 10";
ArrayList<String> sqlList = new ArrayList<String>();
应用开发指南 8 ClickHouse 开发指南(普通模式)
sqlList.add(querySql1);
sqlList.add(querySql2);
ArrayList<ArrayList<ArrayList<String>>> result = util.exeSql(sqlList);
for (ArrayList<ArrayList<String>> singleResult : result) { for (ArrayList<String> strings : singleResult) { StringBuilder stringBuilder = new StringBuilder();
for (String string : strings) {
stringBuilder.append(string).append("\t");
}
log.info(stringBuilder.toString());
} } }
8.4.7 删除表
删除在创建表中创建的副本表和分布式表。
private void dropTable(String databaseName, String tableName, String clusterName) throws Exception { String dropLocalTableSql = "drop table if exists " + databaseName + "." + tableName + " on cluster " + clusterName;
String dropDisTableSql = "drop table if exists " + databaseName + "." + tableName + "_all" + " on cluster
" + clusterName;
ArrayList<String> sqlList = new ArrayList<String>();
sqlList.add(dropLocalTableSql);
sqlList.add(dropDisTableSql);
util.exeSql(sqlList);
}