clickhouse数据导入遇到的问题

1. 采用mybatis写入数据,速度很慢的问题;

采用mybatis拼接sql的方式,可以写入数据,但是效率很低。每秒数据大概200-300条数据记录。

2. 采用jdbc写入数据,可以使用两种数据源

// 新版本的包
import com.clickhouse.jdbc.ClickHouseDataSource;

// 这个包可以
import ru.yandex.clickhouse.ClickHouseDataSource

3. 时间格式设置问题

组织批量写库时的日期时间格式问题。

java.sql.Date sqlPayTime = new java.sql.Date(bill.getPayTime().getTime());
prepareStatement.setObject(39, new Timestamp(sqlPayTime.getTime()));

需要使用sql的Timestamp,不能使用java.util.Date,也不能使用java.sql.Date。

 4. 主键和排序键

在创建表时指定主键,会根据主键创建索引;
主键可以是多个列,不会影响查询性能,而且主键相同的数据可以重复;
一般不指定主键(primary key),而是指定排序键(order by),此时会把排序键作为主键;
排序键和主键可以不同,但此时主键必须时排序键的前缀。

5. 引擎参数问题

CREATE TABLE default.bill
(
    `bill_id` Int64,
    `bill_date` DateTime
)
ENGINE = ReplacingMergeTree
PARTITION BY toYYYYMM(bill_date)
ORDER BY bill_date
SETTINGS index_granularity = 8192;

 这个引擎设置是有问题的。

当排序key相同的数据,在做数据合并的时候,会进行去重处理。如果bill_date相同,就会进行数据合并。

CREATE TABLE default.bill
(
    `bill_id` Int64,
    `bill_date` DateTime,
    `plat_billno` String
)
ENGINE = ReplacingMergeTree(bill_date)
PARTITION BY toYYYYMM(bill_date)
ORDER BY (plat_billno, bill_date)
PRIMARY KEY (plat_billno)
SETTINGS index_granularity = 8192;

这个引擎设置才是正确的,因为账单编号本身是唯一的,所以不会造成数据被覆盖的情况。 

ReplacingMergeTree引擎

该引擎和 MergeTree 的不同之处在于它会删除排序键值相同的重复项。 数据的去重只会在数据合并期间进行。合并会在后台一个不确定的时间进行,因此你无法预先作出计划。有一些数据可能仍未被处理。尽管你可以调用 OPTIMIZE 语句发起计划外的合并,但请不要依靠它,因为 OPTIMIZE 语句会引发对数据的大量读写。

  • ENGINE:引擎名和参数。
  • ver:版本列,类型可以是UInt*,Date,或者DateTime,可选择的参数。合并的时候ReplacingMergeTree从相同的主键中选择一行保留,如果ver列未指定,则选择最后一条,如果ver列已指定,则选择ver值最大的版本。
  • PARTITION BY:分区键。要按月分区,可以使用表达式 toYYYYMM(date_column) ,这里的 date_column 是一个 Date 类型的列。这里该分区名格式会是 “YYYYMM” 这样。
  • ORDER BY:表的排序键。可以是一组列或任意的表达式。例如: ORDER BY (CounterID, EventDate) 。
  • optimize table replacing_test;

    触发合并,可以删除重复记录。

6. 事务提交问题

// 执行conn.setAutoCommit(false);会报Transactions are not supported异常
// 所以不能执行conn.commit();
// 只能执行pst.executeBatch();由clickhouse进行后台提交。测试时插入数据条数是正确的

7. 错误信息

ru.yandex.clickhouse.except.ClickHouseUnknownException: ClickHouse exception, code: 1002, host: 192.168.17.81, port: 8123; Connection pool shut down
        at ru.yandex.clickhouse.except.ClickHouseExceptionSpecifier.getException(ClickHouseExceptionSpecifier.java:100)
        at ru.yandex.clickhouse.except.ClickHouseExceptionSpecifier.specify(ClickHouseExceptionSpecifier.java:57)
        at ru.yandex.clickhouse.except.ClickHouseExceptionSpecifier.specify(ClickHouseExceptionSpecifier.java:26)
        at ru.yandex.clickhouse.ClickHouseStatementImpl.sendStream(ClickHouseStatementImpl.java:1069)
        at ru.yandex.clickhouse.ClickHouseStatementImpl.sendStream(ClickHouseStatementImpl.java:1022)
        at ru.yandex.clickhouse.ClickHouseStatementImpl.sendStream(ClickHouseStatementImpl.java:1015)
        at ru.yandex.clickhouse.ClickHousePreparedStatementImpl.executeBatch(ClickHousePreparedStatementImpl.java:382)
        at ru.yandex.clickhouse.ClickHousePreparedStatementImpl.executeBatch(ClickHousePreparedStatementImpl.java:365)
        at com.ftsafe.quartz.task.ClickBillFromDb.batchInsertClickHouse(ClickBillFromDb.java:398)
        at com.ftsafe.quartz.task.ClickBillFromDb.dataTransProc(ClickBillFromDb.java:143)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at com.ftsafe.quartz.util.JobInvokeUtil.invokeMethod(JobInvokeUtil.java:56)
        at com.ftsafe.quartz.util.JobInvokeUtil.invokeMethod(JobInvokeUtil.java:33)
        at com.ftsafe.quartz.util.QuartzDisallowConcurrentExecution.doExecute(QuartzDisallowConcurrentExecution.java:19)
        at com.ftsafe.quartz.util.AbstractQuartzJob.execute(AbstractQuartzJob.java:43)
        at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: java.lang.IllegalStateException: Connection pool shut down
        at org.apache.http.util.Asserts.check(Asserts.java:34)

8. 对空值的处理

字符串属性为空,BigDecimal属性为空等。通过jdbc批量写入数据时,字段数据不能设置为空值,一旦设置为空值,就会报错,此时需要设置为sql的空值。

prepareStatement.setNull(45, Types.CHAR);

9. 空间不足异常

java.sql.BatchUpdateException: Code: 243. DB::Exception: Cannot reserve 7.24 MiB, not enough space. (NOT_ENOUGH_SPACE) (version 22.2.2.1)
, server ClickHouseNode(addr=http:192.168.17.81:8123, db=test)@1081606924
        at com.clickhouse.jdbc.SqlExceptionUtils.batchUpdateError(SqlExceptionUtils.java:90)
        at com.clickhouse.jdbc.internal.InputBasedPreparedStatement.executeAny(InputBasedPreparedStatement.java:133)
        at com.clickhouse.jdbc.internal.AbstractPreparedStatement.executeLargeBatch(AbstractPreparedStatement.java:85)
        at com.clickhouse.jdbc.internal.ClickHouseStatementImpl.executeBatch(ClickHouseStatementImpl.java:568)
        at com.ftsafe.quartz.task.ClickBillFromDb.batchInsertClickHouse(ClickBillFromDb.java:442)
        at com.ftsafe.quartz.task.ClickBillFromDb.dataTransProc(ClickBillFromDb.java:144)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at com.ftsafe.quartz.util.JobInvokeUtil.invokeMethod(JobInvokeUtil.java:56)
        at com.ftsafe.quartz.util.JobInvokeUtil.invokeMethod(JobInvokeUtil.java:33)
        at com.ftsafe.quartz.util.QuartzDisallowConcurrentExecution.doExecute(QuartzDisallowConcurrentExecution.java:19)
        at com.ftsafe.quartz.util.AbstractQuartzJob.execute(AbstractQuartzJob.java:43)
        at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)

上述错误原因是磁盘空间不足引起。

10. 优化后的性能

采用jdbc批量导入后的性能,基本上每秒写入数据量在1万条左右。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值