alibaba / DataX

DataX是阿里云DataWorks数据集成的开源版本。
Other
15.73k stars 5.39k forks source link

同步数据到clickhouse的datetime64类型,会丢失精度 #1544

Open dingxiaobo opened 1 year ago

dingxiaobo commented 1 year ago
    @dingxiaobo 同步数据到clickhouse的datetime64类型,会丢失精度

sqlserver原表字段类型:datetime(3) image clickhouse字段类型:datetime64 image

Originally posted by @MrZhao1024B in https://github.com/alibaba/DataX/issues/1465#issuecomment-1276955878

zhaoyvli commented 1 year ago

补充:用同一张表做数据源进行测试, 同步到另外一张sqlserver表,时间是没有问题的

Y-evil commented 1 year ago

谁是Reader,谁是Writer? DataX是支持毫秒精度的,只是不支持微秒和纳秒。 你配置的JSON也发下。

zhaoyvli commented 1 year ago

{ "job": { "content": [ { "reader": { "name": "sqlserverreader", "parameter": { "column": [ "[inputtime]" ], "connection": [ { "jdbcUrl": ["jdbc:sqlserver://xxxxxx:1433"], "table": ["test.dbo.a"] } ], "password": "xxxx", "username": "xxxx" } }, "writer": { "name": "clickhousewriter", "parameter": { "batchByteSize": 134217728, "batchSize": 65536, "column": [ "inputtime" ], "connection": [ { "jdbcUrl": "jdbc:clickhouse://xxxxxxxxx:8123/ods", "table": [ "a" ] } ], "dryRun": false, "password": "xxxxxxx", "preSql": ["truncate table ods.a"], "username": "xxxxxxx", "writeMode": "insert" } } } ], "setting": { "speed": { "channel": "1" } } } }

sqlserver是Reader,clickhouse是Writer 我是用当前master分支的代码编译的

Y-evil commented 1 year ago

是不是clickhouse-jdbc版本太低了,你升级到最新的试试。

Release v0.3.0 support more data types: IPv4, IPv6, Int128, UInt128, Int256, UInt256, Decimal256, DateTime*, and Map

他到0.3.0版本才支持DateTime64;

Y-evil commented 1 year ago

应该就是clickhouse-jdbc版本太低的原因。 在0.3.2版本中对TimeStamp的处理如下,有对纳秒精度的处理逻辑: public static String formatTimestamp(Timestamp time, TimeZone timeZone) { SimpleDateFormat formatter = getDateTimeFormat(); formatter.setTimeZone(timeZone); StringBuilder formatted = new StringBuilder(formatter.format(time)); if (time != null && time.getNanos() % 1000000 > 0) { formatted.append('.').append(time.getNanos()); } return formatted.toString(); }

在0.2.4版本中 public static String formatTimestamp(Timestamp time, TimeZone timeZone) { getDateTimeFormat().setTimeZone(timeZone); return getDateTimeFormat().format(time); }

getDateTimeFormat()方法返回的是这个

private static ThreadLocal dateTimeFormat = new ThreadLocal() { @Override protected SimpleDateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } }

zhaoyvli commented 1 year ago
  1. 升级 clickhouse-jdbc 版本 image 同步数据报错 (类似 #1484,已经更新了代码,依然存在该问题),日志: 日志.txt

  2. 升级 clickhouse-jdbc 版本 image 同步数据报错 日志: 错误日志.txt

修改 driver class image

同步数据报错: 错误日志2.txt

Y-evil commented 1 year ago

看错误日志2.txt,似乎与列的时区TimeZone有关

补充:对于带时区的的TIMESTAMP,DataX没有对Types.TIMESTAMP_WITH_TIMEZONE处理/支持。

Types.TIMESTAMP = 93,一般都是使用这个。 Types.TIMESTAMP_WITH_TIMEZONE = 2014。

zhaoyvli commented 1 year ago

字段类型 DateTime64(3, 'Asia/Shanghai') -> DateTime64(3),同步数据会存在 NullPointerException 错误日志3.txt

Y-evil commented 1 year ago

你原表里有null值,clickhouse-jdbc对NULL处理的有点问题。

升到最新0.3.2-patch11试试 或者将该列显式设置为Nullable

你看下这个issue https://github.com/ClickHouse/clickhouse-jdbc/issues/878