一、项目介绍
根据公司MySQL数据库中存储的业务数据,针对用户相关一些维度,提取用户相关的属性字段,其中包括属性字段直接提取,金额字段的计算提起,日期字段的格式转换等,最终将一个用户的各个属性在页面进行展示。
二、项目架构
项目使用的是MySQL Sqoop Hadoop Hive进行的离线数据处理,其中大数据相关的框架使用的是CDH平台集成的。
整个项目中用到了很多知识,比如:shell脚本、Sqoop导出导入语句、hive数据合并、hive数据ETL等等。
三、遇到的问题
1、Sqoop相关
1.导出问题
CDH中的Sqoop导出有一个问题,就是导出的时候不显示错误信息,错误信息需要在CDH的web页面中去查看,而控制台只显示导出中断,任务失败的信息。
具体解决方法请参见本人之前的文章:CDH的坑之Sqoop导出数据到MySQL
2.分隔符选择
一开始对数据不是很了解,选择了t作为数据的分割符,导出的数据在统计的时候出现了问题,字段对应不上,在检查数据的过程中,发现在数据中某些字段包含了t,那么这个分隔符就不能使用了,果断的换了竖线“|”,问题暂时得到了解决,为什么说事暂时得到解决?
不知道业务方和开发是怎么定义的数据,就怕后期数据存储过程中出现竖线,那么到时候就又需要换了。
3.导出更新或者插入
为了实现导出到数据库中的数据,数据库中已经存在的,更新,不存在的进行插入,开始为了顺利进行数据导入,在MySQL中创建的表没有任何约束,那么在使用Sqoop更新模式的时候,使用了allowinsert模式,但是数据却全是插入的,没有实现本人想要的操作。
最后经过一番测试,发现要想实现本人理想的效果,MySQL中的表被指定的update-key字段必须唯一非空才行,让后将id字段添加为主键,效果实现了。
2、Hive相关
1.合并数据
在原始的业务数据中,本公司的订单表是按照每月一张进行存储的,这个需要进行数据合并。
数据合并刚开始一直考虑怎么把所有的数据合并到一张表中去处理,而这个思路直接就搁浅了,好像Sqoop做不到,只能将数据导入到hdfs中再进行合并,如果直接合并的话,新数据又是一个问题,怎么让新数据也合并到这个表中?
想过使用增量导入,但是问题在于MySQL中的表不是一张,而是一个月一张表。
最后在网上查到了一个方法,那就是外部分区表,将每个表分别以分区的目录导入HDFS中,然后在Hive中创建一个外部分区表,然后再将每个分区添加到表中,这样所有的数据都合并到了一个库中。
具体详情参见本人之前的文章:Hive应用:外部分区表
2.表字段不一致
本公司成立也好多年了,订单表也堆积了好几年的数据,那么在公司发展的过程中,表中的字段也发生了改变,一些字段的顺序发生了改变,增加了一些字段,也删除了一些字段,这样在表合并的时候,表格式对不上,最后提取的数据肯定不准确。
期初为了保证数据的完整性考虑,建立一张字段完整的表,将数据导入,可是这样做,根本不知道那张表是更改过的,期间表设计更改了几次,这样做Sqoop的导入语句好像并不能实现。
最后,经过确认,使用到的所有字段,在所有的订单表中都是存在的那么就选择了局部字段导出。
3.日期格式转换
hive中的日期格式转换比sql的要麻烦一些,sql中使用一个函数就解决的,在Hive中需要使用多个内置函数才能解决,并且还是嵌套函数,使用的时候注意思路,比较绕。
4.小数计算
当全部数据导入之后,进行数据聚合的时候发现,好像出现了无限小数。这个问题困扰了我好长时间,因为数据计算只涉及到简单的加减法,没有乘除等更高级的计算,怎么会出现无限小数呢?
观察原始数据发现,订单表中的所有金额都是使用float类型存储的,突然想到,计算机不能精确存储小数,更别提计算的精确性了,以前做web项目的时候数据库都是采用整数存储小数,前台展示的时候再转化为小数,没想到公司的设计这么的让人无以言表啊。
那么发现问题的根本之后,就好解决了,本人在导数据的时候,就将这些小数先转化为整数,然后再导入HDFS进行存储,那么在计算的过程中就不会出现不精确的情况了,前台使用的时候,再转化为小数展示。
导出的过程中,发现即使使用了MySQL的floor()函数,存储到HDFS中的数据也是带着小数点的,这个暂时没弄明白,不过小数部分都是0就不会影响计算了。
计算结果导出的时候,发现没有了小数点,很神奇。
5.hive表分区添加
在设计了外部分区表之后,发现本公司的数据一共有200个左右的分区,手写这些分区,还不得写死啊,就想使用一种方法,让它自己循环添加,这才符合一个程序员的思想,在考虑中Hql语句肯定是不行了,Shell脚本个人感觉也不是太好,那么最后我选择了Hive的Java JDBC编程来实现这个事情,可能是因为本人可以熟练的使用Java,所以觉得这个比较好用。
利用Java写循环语句,进行添加即可。
后期我会将这个方法单独写一篇文章,到时候将连接黏贴过来。
6.hive自增字段设置
业务需要一个自增的id作为中间表的唯一标识,那么hive中好像没有提供这个方法,经过一番查找,本人用了一个变种的方法,那就是row_number() over()这两个方法联用,就会自动生成一个自增的字段。
就单独写这两个方法,不需要多余的参数,例如:
代码语言:javascript复制insert into table user_1 select row_number() over() as id,username,age from user;
3、shell相关
在写shell脚本的时候,发现了写出的包含Sqoop语句的脚本,直接运行没有问题,当放入定时列表运行的时候,会报错,报的是找不到java环境,这种情况着实让我头疼。
后来经过资深的运维大哥告知,在脚本中Sqoop语句之前加入java的环境变量即可解决这个问题,试了之后,果然没问题,不愧是资深的运维大哥啊。
加入的环境和Linux系统中的java环境变量一致即可,如下:
代码语言:javascript复制export JAVA_HOME=java安装路径
export PATH=$PATH:$JAVA_HOME/bin
#或者
JAVA_HOME=java安装路径
PATH=$PATH:$JAVA_HOME/bin
export JAVA_HOME PATH
四、总结
以上就是本人这个项目中遇到的问题,想做好一个项目,需要方方面面的知识来支持,需要仔细认真的考虑,不能有任何遗漏,一旦出现纰漏那么就是问题爆发的地方。这个项目很简单,但是暴露出了很多常见的问题,以后再遇到类似的问题之后,就会很快的解决,对自己的知识也有了一定的增长。
我相信,大多数人都有眼高手低的时候,比如:本人上面出现的Sqoop导出的语句,不就是导出吗,以前用开源框架的时候,什么问题都会在控制台暴露出来,可是现在用了CDH就让自己傻眼了,实践出真知,亘古不变的真理,人不能犯懒,一定要多尝试,多实践。
在此与大家共勉,共同进步!
代码语言:txt复制 (adsbygoogle = window.adsbygoogle || []).push({});