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