Java项目中Clickhouse大数据量插入
背景
最近,因为项目中使用到了Clickhouse数据库,本着MySQL数据库的思维,直接使用了Java + MP的实现方式,将大批量数据插入到Clickhouse中。由于MP的批量插入接口默认只支持1000的数据量,于是理所当然地将这批数据分页后再插入,便心安理得的交差了。
可是,后面项目测试后发现,只是单处理100w的数据就需要1h+的时间。一开始怀疑是程序内存不够导致频繁GC,所以就想着直接加大内存。后来内存加大后,性能并没有得到质的提升。
接着开始debug,这时才发现项目的瓶颈其实都在数据落库上。可是Clickhouse是专门应对大数据场景的数据库啊,不可能这么慢啊。于是开始查找Clickhouse相关大数据插入的资料,发现Clickhouse对大数据的导入性能支持得很好,于是便思考着能不能在项目上也应用上。最后终于在官方issue上找到最佳导入实践,通过测试后发现现在导入100w的数据直接缩短为了5m,这可是10倍性能的提升啊!!!话不多说,开始我们的实践吧。
代码实现
导入依赖
<dependency>
<groupId>com.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.clickhouse</groupId>
<artifactId>clickhouse-client</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
</dependency>
- 由于需要先将数据生成附件,再通过附件导入Clickhouse。所以这里直接使用easyexcel将数据生成csv文件;
- 其他两个依赖主要是针对Clickhouse提供的jdbc客户端。
定义Clickhouse配置信息
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* ClickHouse 连接信息配置
* </p>
*/
@Data
public class ClickHouseNodeProperties implements Serializable {
/**
* ClickHouse 连接信息 <br/>
* eg: http://192.168.1.1:8123/test
*/
private String uri;
/**
* ClickHouse 用户名
*/
private String username = "";
/**
* ClickHouse 密码
*/
private String password = "";
/**
* Maximum query execution time in seconds, 0 means no limit.
*/
private Integer maxExecutionTime = 0;
/**
* Socket timeout in seconds.
*/
private Integer socketTimeout = 3600;
/**
* Session timeout in seconds. 0 or negative number means same as server default.
*/
private Integer sessionTimeout = 3600;
/**
* Connection timeout in seconds. It's also used for waiting a connection being closed.
*/
private Integer connectionTimeout = 120;
}
封装Clickhouse客户端
import cn.hutool.core.util.StrUtil;
import com.clickhouse.client.ClickHouseCredentials;
import com.clickhouse.client.ClickHouseNode;
import com.clickhouse.client.config.ClickHouseClientOption;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.