把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的内容处理真的很强大,这种琐碎的细节内容处理简直得心应手。

0

发表评论

电子邮件地址不会被公开。

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>