把mysql表导入到hive的注意点

我相信很多厂有把mysql表数据增量导入hive的需求,最近我有这个需求所以把注意点分享一下。

首先,这个任务大家肯定会想到sqoop这个专门的工具,我在折腾了很久这个工具之后意识到sqoop的可定制性太差了,很多细节没法自己控制,比如:

1、如果你要对一些字段进行脱敏或者增减字段,sqoop做不到;或者你想对hive表建表做一些定制,sqoop也许可以做到不过我真的没耐心学了hive还得再去学sqoop语法

2、增量备份的时候sqoop允许你指定从哪个id开始备份,可是加入你cron每天备份还是得自己脚本记录上一次id备份到哪里了,这哪是自动化

3、假如增量备份出错了,你很难知道问题出在哪里,你甚至很难知道哪些数据已经导入,哪些没有,如果我重启动sqoop导入的话是否会有数据重复

4、sqoop里面的确可以控制许多细节,比如指定怎么处理null值,指定分隔符、换行符、压缩等等,可是我已经学了hive了就为了备份凭什么还要去学去查你sqoop的那一套约定;就跟我已经熟练掌握了一门编程语言和正则处理,结果为了处理文本数据跑去学sed awk语法一样蛋疼;而且sqoop2还搞了个啥job之类的复杂的东西,搞这么复杂我干嘛直接在cron里面每天凌晨跑个脚本就弄好了

所以我的建议是,操起自己最熟悉的语言,手写一个脚本定期从mysql中导出文本数据,然后调用hive命令行把文本数据导入即可,简简单单+完全定制。这里我以php作为例子,来说明一下大概思路。

1、hive建表,照着mysql的表写hive表,字段分隔符’\001’+记录分割’\n’,我是把建表语句写成一个sql文件,然后php再exec调用hive的(我不太喜欢shell),这样可以尽量自动化:


$o = null;

$r = null;

$exec_str = "hive -f {$sql_table_file}";

exec ( $exec_str, $o, $r );

if ($r !== 0)

{

$msg = var_export ( $o, true );

echo $msg;

exit ();

}

2、增量备份,比如脚本指定按照mysql的ID字段遍历备份,并且log记录下每次遍历到哪里了,那么后一天的自动备份脚本去log中读上次备份记录就OK了。

3、如果你hive表用’\001’做字段分割+’\n’做行分割,那么从mysql中select出来的每个字段必须过滤掉’\001’和’\n’,遇到null字段要替换成”\N”,要把”‘”替换成”\'”,然后把记录按照hive的格式导出成txt文本文件。

4、php再exec调用hive用语法`load data local inpath…`导入文本文件即可,分区你也可以非常自由的自己控制。

5、我的建议是如果表数据不大hive表不用压缩,如果表太大了或者hdfs空间不够,那么最好使用压缩表,但问题是我这个方法是自己生成的一个文本文件,这个文本文件只能导入TEXTFILE类型的非压缩hive表。解决方法很简单,就是用一张临时TEXTFILE的非压缩表先导入数据,然后再转存压缩表,最后清空非压缩表。

6、非常细心的处理每一步的log,遇到错误能够判断出错在哪里,哪些数据已经导入了hive;如果把脚本添加到cron中注意让脚本只能单例运行

7、不要在脚本中直接往hiveserver2中插大量数据,这样速度慢不说,业界更常规的办法是hive命令行导入,hiveserver2比较适合查询

总结下来其实很简单,实际上就是这么简单,比sqoop简单多了。

最后感慨一下php的内容处理真的很强大,这种琐碎的细节内容处理简直得心应手。

发表评论

电子邮件地址不会被公开。 必填项已用*标注