使用Sqoop将Hive数据导出到TiDB

关系型数据库与大数据平台之间的数据传输之前写过一些
使用Sqoop将数据在HDFS与MySQL互导
使用Sqoop将SQL Server视图中数据导入Hive
使用DataX将Hive与MySQL中的表互导
使用Sqoop将Hive数据导出到TiDB虽然没写过,但网上一堆写的,那为什么我要专门写一下呢?
我发现一些大家可能会忽略但很重要的地方!
所以,请继续看下去,你肯定会有收获的!!!


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 '\001'
;

2 建TiDB表

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

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

3 Sqoop 脚本

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

#!/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 '\001' \ # 与hive表分隔符一致
--num-mappers 5 \ # 根据数据量确定,写太大会导致小文件过多,太小跑不动
--input-null-string '\\N' \ # 将字符串类型字段中的\N替换为null
--input-null-non-string '\\N' \ # 将非字符串类型字段中的\N替换为null
--columns "contract_no,plan_date,dt"

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

--null-string '\\N' \ # 将字符串类型字段中的null值替换为\N
--null-non-string '\\N' \ # 将非字符串类型字段中的null值替换为\N

4 问题排查

查看报错日志,注意加粗部分,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);
}

5 问题处理

经过上面排查,问题已经定位到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);

### 回答1: 可以使用以下代码来查看当前文件所在目录: ```lua local current_dir = debug.getinfo(1).source:match("@?(.*/)") print(current_dir) ``` 这段代码使用了 Lua 的 debug 库来获取当前文件的信息,然后通过正则表达式来提取出当前文件所在的目录。 ### 回答2: 在Python中,我们可以使用os模块来操作操作系统相关的功能。如果我们想要查看当前文件所在目录,我们可以使用os模块中的`os.getcwd()`方法。 `os.getcwd()`方法会返回当前文件所在目录的路径字符串。这个路径字符串表示当前Python脚本文件所在的目录,即当前工作目录。 下面是一个示例代码来演示如何使用os模块来查看当前文件所在目录: ``` import os # 获取当前文件所在目录 current_dir = os.getcwd() # 打印当前文件所在目录 print("当前文件所在目录:", current_dir) ``` 上面的代码中,我们首先导入了os模块。然后使用`os.getcwd()`方法获取当前文件所在目录的路径字符串,并将其赋值给变量`current_dir`。最后,使用`print()`函数打印出当前文件所在目录。 运行以上代码,你将会在控制台中看到类似下面的输出: ``` 当前文件所在目录: C:\Users\username\Documents ``` 以上就是使用os模块查看当前文件所在目录的简单介绍和示例代码。希望能对你有所帮助! ### 回答3: 要使用os模块来查看当前文件所在目录,首先需要导入os模块。然后,可以使用os.getcwd()函数来获取当前工作目录的路径。该函数没有任何参数,直接调用即可。返回的是一个表示当前工作目录路径的字符串。 示例代码如下: ``` import os current_dir = os.getcwd() print("当前文件所在目录为:" + current_dir) ``` 执行以上代码,会输出当前文件所在目录的路径。 当你运行这段代码时,它会返回当前脚本文件所在的目录。例如,如果当前文件在`/user/desktop/test.py`路径下,运行以上代码会输出`/user/desktop`。 这样,使用os模块就可以轻松查看当前文件所在的目录了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

光于前裕于后

您的打赏将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值