相关推荐recommended
使用Sqoop将Hive数据导出到TiDB
作者:mmseoamin日期:2024-01-18

关系型数据库与大数据平台之间的数据传输之前写过一些

使用Sqoop将数据在HDFS与MySQL互导

使用Sqoop将SQL Server视图中数据导入Hive

使用DataX将Hive与MySQL中的表互导

使用Sqoop将Hive数据导出到TiDB虽然没写过,但网上一堆写的,那为什么我要专门写一下呢?

我发现一些大家可能会忽略但很重要的地方!

所以,请继续看下去,你肯定会有收获的!!!


文章目录

    • 1 建Hive表
    • 2 建TiDB表
    • 3 Sqoop 脚本
    • 4 问题排查
    • 5 问题处理

      1 建Hive表

      注意分隔符 ‘\001’,用别的也可以,但要和Sqoop命令一致

      create table test_table(
           contract_no                         string                  COMMENT '合同号'
          ,plan_date                           date                    COMMENT '应还日期'
          ,dt                                  string                  COMMENT '数据日期'
      )
      comment '测试表'
      row format delimited fields terminated by '

      2 建TiDB表

      1' ;
      create table test_table(
           id bigint PRIMARY KEY AUTO_INCREMENT
          ,contract_no                         varchar(50)             COMMENT '合同号'
          ,plan_date                           date                    COMMENT '应还日期'
          ,dt                                  varchar(10)             COMMENT '数据日期'
      );
      

      注意TiDB表多了个自增主键 id

      3 Sqoop 脚本

      #!/bin/sh
      source /etc/profile
      sqoop export --D mapred.job.queue.name=xxx \
      --connect jdbc:mysql://xxx:3306/xxx \
      --username xxx \
      --password xxx \
      --table test_table \
      --export-dir /user/hive/warehouse/dwd.db/test_table/ \
      --input-fields-terminated-by '
      --null-string '\N' \ # 将字符串类型字段中的null值替换为\N
      --null-non-string '\N' \ # 将非字符串类型字段中的null值替换为\N
      
      1' \ # 与hive表分隔符一致 --num-mappers 5 \ # 根据数据量确定,写太大会导致小文件过多,太小跑不动 --input-null-string '\N' \ # 将字符串类型字段中的\N替换为null --input-null-non-string '\N' \ # 将非字符串类型字段中的\N替换为null --columns "contract_no,plan_date,dt"

      注意如果源表和目标表字段不完全相同,可以使用 --columns 选取部分字段,这里因为TiDB表多一个自增id,使用 --columns “contract_no,plan_date,dt”

      4 问题排查

      上面是将hive数据export导出到tidb。注意在hive中null值默认存储成了\N(可修改),所以在import导入Hive时需要加下面命令。注意export和import区别!!!

      5 问题处理

      黄山旅游攻略一日游

      查看报错日志,注意加粗部分,Sqoop会生成一个“同步表名.java”文件,查看报错所在行,定位问题。

      Caused by: java.lang.RuntimeException: Can’t parse input data: ‘\N’

      at test_table.__loadFromFields(test_table.java:765)

      at test_table.parse(test_table.java:648)

      at org.apache.sqoop.mapreduce.TextExportMapper.map(TextExportMapper.java:83)

      … 10 more

      Caused by: java.lang.IllegalArgumentException

      at java.sql.Date.valueOf(Date.java:143)

      at test_table.__loadFromFields(test_table.java:722)

      … 12 more

      找到722行,发现plan_date字段有null值,因为hive中null值存储成了\N,而该字段是date类型,从hive到tidb时插不进去。

      if (__cur_str.equals(“null”) || __cur_str.length() == 0) { this.plan_date = null; } else {

      this.plan_date = java.sql.Date.valueOf(__cur_str);

      }

      大连网站建设公司

      经过上面排查,问题已经定位到plan_date字段中有null值,有两个解决方案,一是将null值替换为默认值,一是保留null值,加上下面两个参数。因为hive中null值默认存储成了\N(可修改)!!!

      –input-null-string ‘\N’ \ # 将字符串类型字段中的\N替换为null

      –input-null-non-string ‘\N’ \ # 将非字符串类型字段中的\N替换为null

      PS:TiDB表加索引不影响Sqoop

      CREATE INDEX idx_source_date ON tabname(col1, col2);