java 实现 Hive 导入到 mysq

[程序名] HiveToMysql

[作用  ] 从 hive 导出数据到 mysql

[描述  ] 由于 sqoop 对以下功能支持不好:
1.导出-导入字段的映射
2.只导入部分字段
3.导出时无法设置常量值给导入字段
4.支持重复导入/清除重复数据
故开发此程序,支持以上功能.
[用法  ] 运行 wrap_all.sh.


[额外  ] 本程序在处理出错时会返回错误码给上层调用者, 可以兼容 Tss 捕获脚本运行的错误. Tss 中将 wrap.sh 指定为运行脚本即可.


[配置  ] dump.conf 是总体配置文件.它指明了 hive 和 mysql 的库信息, 以及一些导出-导出配置, 如下:
1.dump.conf 中 ds 表示要导出大数据某个日期的数据. ds 不设置或设置为 ? 表示取上一个自然日期
2.一般情况下 dump.conf 变量的配置不需要更改.它们都有默认值.
3.delete_before_dump(默认为 false) 若设置为 true 则先从 mysql 库删除数据(where 条件参考的是 map 文件中配置的常量,见 map 配置),一般应该这样做,这样
可以支持重复导入. 但是如果程序的逻辑不支持这样做,应该设置为 false.
4.skip_dump_to_local_file 跳过导出 hive 数据到本地,(以 skip 开头的参数主要用于测试)
5.skip_local_file_to_sql 跳过从本地 hive 数据(即上一步的输出)生成 sql 文件
6.skip_sql_to_target 跳过从 sql 文件(上一步的输出)导入到目标库
7.error_if_none_data 如果 hive 没有满足条件的数据是否应该中止处理(error: 9998)
8.error_if_src_field_not_exsits 如果 map 中指定的 hive 字段并不存在是否应中止处理(error: 9997)
9.返回给上层调用者的错误码:
9995: hive 导出缺失表头
9996: hive 导出的数据与表头对应不上
9997: hive 字段不存在(error_if_src_field_not_exsits=true 时生效)
9998: 没有数据(error_if_none_data=true 时生效)



 dump.conf 配置了hive 表到 mysql 表的字段映射. 
1.配置的格式为 mysql_field=hive_field. 
2.为了支持导入 mysql 时给字段设置常量,可以给等式右边赋为以 $ 或 # 开头的量.$ 表示后面的变量在 dump.conf 中配置了, # 表示立即数
3.只有配置在该文件中的 mysql 字段会被导入值, 没有配置的字段被忽略.这允许了部分字段导出-导入.
4.配置在该文件中的常量($ 或 # 引导的字段和值)将被用于导入 mysql 前删除.


开发此程序时,遇到以下问题,给出了相应的解决方法

1.java 内部调用 shell 命令,如何实时获得输出流并显示?

  很显然, java 中需要等待 shell 命令执行完毕, 获得 shell 输出简单的做法是等 shell 执行完毕后读 shell 的输出流. 如果要实时地获得,此时需要新开启一个线程,去获取 shell 进程的输出流并打印出来。

这里有两个问题。第一,进程一般有两个输出流: 标准输出流和标准错误流,如果只开启一个线程去读其中的某一个流,将会错过另一个输出流上的信息,这样看起来就不是实时输出。因此,我们需要开启两个线程,分别获得这两个输出流,分别打印。第二,由于进程的输出流一般是缓冲的,可能有延迟,但由于我们并不知道 shell 进程的源代码,因此也不能强制刷新缓冲区,实现实时打印,导致的结果是,我们不能宛全实现实时打印。

设想过能否在调用进程中设置子进程的输出,使其不带缓冲。但没有找到方法,如果谁找到了,麻烦回复一下这篇文章

2.重定向到文件,文件是增加模式?

由于本程序会重定向中间结果到一个文件,发现每次运行后,中间文件都会定长地增加。猜测是由于重定向写文件的模式是 append,因此,每次重定向前清空一下文件。

3.导出的 hive 数据中,会有多个表头. 需要防止这种情况

在导出的数据中,发现有多个表头(使用 hive -e "select * from" >> mid.data 命令导出到中间文件),它们似乎不等于第一行的表头,看起来多了 hive -e , 一些命令,不管怎样,判断这一行的字符串是否包含了第一行的表头即可。

4.sqoop 暂时不支持字段名到字段名的映射,一般导数时, 指定的是 mysql 字段名,sqoop 使用顺序和它进行对应.

这个是研究了 sqoop 后观察到的结果,暂时没有找到字段名和字段名的对应设置

5.使用命令:hive -e 'select * from %s where ds=%s'>>%s,注意,应该是 shell 命令的输出重定向,而不是 select 的重定向,因而不能写为:

hive -e 'select * from %s where ds=%s>>%s'

6.java 内部调用 shell命令时,特殊字符 << | 需要使用 ProcessBuilder 调用 sh ,将所有的命令作为它的参数。原理待研究。


代码开源地址 : https://github.com/juniorfans/hiveToMysql/blob/master/HiveToMysql.java


你可能感兴趣的:(Java)