Kudu ImportCsv 行以分隔符结尾

1. 背景

可以通过不同的方式把数据导入到csv,其中kudu就自带有通过mapreduce方式高效把csv文件导入到自身的工具:ImportCsv. 例如有以下数据的csv文件:

1,name_1,21
2,name_2,22
3,name_3,

其中”,”我们叫做分隔符号,当把以上3个记录的csv文件导入到表t_user(id bigint,name string,age int)时,会发现最终只有id=1,2的记录成功导入。我们理想的情况是3条数据都能导入表,且id=3的记录age为值空。

2. 问题分析

通过追踪kudu的java客户端代码发现了像 3,name_3,这样的行数据最终是会抛出异常的(使用ImportCsv的时候可以配置跳过有异常的行,继续往下导数据),定位到org.apache.kudu.mapreduce.tools.CsvParser类的parse方法,部分代码片段:

这里写图片描述

根据代码的逻辑可以得出:以分隔符结尾的行,最后的一列会被抛弃。
所以3,name_3,这一行只会被认为有两个列的值而已,而创建表时的列有3个,最后在导数据时抛出“Not enough columns”异常。

3. 解决方法

为了改动最少的代码以及本来的逻辑,最后选用通过补充字节来解决:既然以分隔符结尾会被当成少一列来处理,那么在本行最后再添加一个分隔符,变成了3,name_3,, ,这样就会被当成3个列了,最后一个列的值为空。

4. 解决步骤

下载相应的源码,稍微修改对应类的逻辑即可

4.1 下载源码

github下载:https://github.com/cloudera/kudu
或者cloudera库下载:http://archive.cloudera.com/kudu/kudu/5/

4.2 修改逻辑

解压后找到java/kudu-client-tools目录下的ImportCsvMapper.java类文件,我们只需要修改这个类的代码即可:

  1. 为类ImportCsvMapper添加属性
    这里写图片描述

  2. setup方法中初始化添加的属性

    这里写图片描述

  3. 给以分隔符结尾的行补充字节
    这里写图片描述

4.3 添加配置

单独编译kudu-client-tools模块需要将checkstyle_suppressions.xml拷贝到kudu-client-tools根目录:

这里写图片描述

4.4 重新编译

注意,只需要单独编译kudu-client-tools模块即可,打开CMD路由到java\kudu-client-tools目录执行以下命令编译:

mvn package -DskipTests

成功后在target目录下可以看到打出的jar包:

这里写图片描述

我们只需要使用下面的包来导数据即可,它已经包含了相关的依赖。

5. 重新导入

5.1 创建kudu表

CREATE TABLE T_USER (
  id BIGINT ,
  name string  ,
  sex String,
  PRIMARY KEY(id)
)PARTITION BY HASH PARTITIONS 16 STORED AS KUDU;

注意:这里为了方便所以所有的字段都创建为字符串,因为原来的csv文件有些本来应该是数字的但是存了空值,而空值在使用ImportCsv时转为数字会出错。

5.2 导数据

使用上步骤编译生成的xxxx-with-dependencies.jar包

hadoop jar /data//kudu-client-tools-1.2.0-cdh5.10.0-jar-with-dependencies.jar org.apache.kudu.mapreduce.tools.ImportCsv -Dkudu.master.addresses=master:7051 -Dimportcsv.skip.bad.lines=true  '-Dimportcsv.separator=,'  'id,name,sex' impala::impala_kudu.T_USER hdfs://master:8020/data//part-m-000.csv

5.3 验证

通过查询数据来验证是否3条记录都已经导入表

这里写图片描述

可以看到三条记录都已经可以导入到KUDU里了。

猜你喜欢

转载自blog.csdn.net/czmacd/article/details/60954280
今日推荐