hive表自增列实现方法(完全实现表中数据自增列唯一)之优化一(加快文件处理速度,已经非常非常快了)

4 篇文章 0 订阅

        Hive表自增列的实现,我在网上找了好久,大都是自己编写UDF(或者是UDAF/UDTF)之类的,或者是直接使用hive的lib库中提供的jar包,加载之后创建方法,然后在hive sql中调用,不过这些都会遇到一个问题:在多map任务的SQL中,每个map处理之后的多个文件,每个文件中的记录都是从1开始自增,并不能真正的实现hive表中所有的记录都有唯一编号,而且是自增的效果。在和别人讨论时,有人提到过一个比较好的方法:

  使用shell脚本处理hive表下的文件:

            1. 下载hive表对应的文件到linux本地系统。

           2. shell命令读取文件的每一行内容,然后在最开始添加自增编号以及行字段分隔符(这个分隔符是在hive建表时指定的,要和建表语句分隔符保持一致),之后将处理之后的该行内容,写入新的文件中。

            3. 将新的文件上传到带有自增列的hive表中。
    下面是我的代码:

        1. 创建原始表,不包含自增列

CREATE TABLE `test.wzq_matcheducation_temp`(

  `userid` bigint,

  `value` string)

ROW FORMAT DELIMITED

  FIELDS TERMINATED BY '\t'

  NULL DEFINED AS ''

STORED AS INPUTFORMAT

  'org.apache.hadoop.mapred.TextInputFormat'

OUTPUTFORMAT

  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'

location信息:/user/hive/warehouse/test.db/wzq_matcheducation_temp

        2. 创建数据表,包含自增列:

CREATE TABLE `test.wzq_matcheducation`(

  `id` bigint,

  `userid` bigint,

  `value` string)

ROW FORMAT DELIMITED

  FIELDS TERMINATED BY '\t'

  NULL DEFINED AS ''

STORED AS INPUTFORMAT

  'org.apache.hadoop.mapred.TextInputFormat'

OUTPUTFORMAT

  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'

location信息:/user/hive/warehouse/test.db/wzq_matcheducation

3. 编写hiveSQL,将数据导入原始表:

insert overwrite table test.wzq_matcheducation_temp

select userid, matcheducation

from bidp.user_cloud

where matcheducation like '%8%'

order by userid

4. 编写文件自增列数据处理shell脚本(重要)!!!脚本很简单,自己看吧。

#!/bin/bash

base_path=/home/work/modify_hbase/shell/column_auto_increment

read -p '------请输入要处理的hive表文件对应的目录路径:' hdfs_path_old
read -p '------请输入有自增列的hive表文件对应的目录路径:' hdfs_path_new

echo -e "------`date "+%y/%m/%d %H:%M:%S"`:正在下载hive表对应目录下的所有文件到linux系统中"
rm -rf $base_path/data
mkdir -p $base_path/data/tmp_old
mkdir -p $base_path/data/tmp_new
hadoop fs -get $hdfs_path_old/* $base_path/data/tmp_old
echo -e "------`date "+%y/%m/%d %H:%M:%S"`:hive表对应目录下的所有文件下载完毕"

cd $base_path/data/tmp_old

#给每个文件添加自增列
i=1
for file in $(ls)
    do
        cat $file | while read line
            do
                echo -e "$i\t$line" >> $base_path/data/tmp_new/$file
                let i++
            done
    done

echo -e "------`date "+%y/%m/%d %H:%M:%S"`:每个数据文件的自增列添加完毕,开始上传所有处理完的数据文件..."
hadoop fs -put $base_path/data/tmp_new/* $hdfs_path_new
echo -e "------`date "+%y/%m/%d %H:%M:%S"`:数据上传完毕,请手动检查结果:1.查询几条数据;2.查询自增列最大值;3.查询表数据量;4.对比2和3的结果是否一致"

exit 0

下面给出脚本代码截图:

5. 执行脚本

                 

两个文件路径分别是原始表数据文件路径和数据表数据路径。执行开始之后,查看脚本执行时输出的日志即可。执行完之后,按照脚本中说的方法进行检查即可。

   以上就是为hive表添加自增列的方法,不过这个方法也有很多局限性,比如文件内容修改速度很慢(shell脚本读写文件较慢,我觉得可以使用java程序读取hdfs上的文件,然后进行批处理之类的,可以加快文件处理速度)、如果单个文件过大,大量占用机器内存(可以将文件做切割处理)。

重点!!!优化

1. shell脚本按行处理文本文件优缺点(针对该需求来说):
    1. 优点:
        1. 脚本代码编写简单
        2. 易测试,边写边测
    2. 缺点:
        1. 处理速度极慢
        一个532.2 M的文件,3300w行,给每行数据之前添加一些内容,然后写入新的文件,需要超过10分钟的时间。
        2. shell脚本不能直接处理hdfs文件系统上的文件,还需要先把需要处理的文件下载下来,然后再进行处理,最后再把处理完的文件上传到hdfs上。
2. java程序按行处理hdfs上的文件优缺点:
    1. 优点:
        1. 处理速度极快:
        一个2.1 G的文件,8100w行,给每行数据之前添加一些内容,然后写入新的文件,只需要不到50秒的时间。和shell脚本处理文件的速度换算一下,大概是将10分钟缩短到了10~20s吧,这还不算shell脚本上传下载文件的时间。总之,java程序处理文件的速度要快得多!!!
        2. 省去下载上传文件的步骤:
        java程序可以创建hdfs文件的输入输出流,包装为按行处理的流之后,可以直接按行读取HDFS上的文件,然后直接写入HDFS新的文件中,而不用将HDFS上的文件下载到linux本地,处理完之后,将新的文件上传到HDFS。
    2. 缺点:
        1. 代码编写比较繁琐:
        需要将文件流进行包装,需要研究各种文件流的操作方式,写bug,改bug……。
        2. 测试、运行比较繁琐:
        不像shell脚本,写完之后就可以直接运行测试,java程序需要打包、上传、然后才能提交给Hadoop执行(公司有跳板机,不能直接连接服务器!!!MMP,测试程序烦得要死!!!)。
3. java程序代码
    这是个IDEA编写的项目,导入IDEA即可查看。jdk版本:1.8
    码云地址:https://gitee.com/wzq246810/file-auto-increment.git(丢失了,无法恢复了)
注意:由于我的码云账号之前重建过一次,所有之前的项目都丢失了。。。。

建议使用 hive sql 中的 row_number() over() 开窗函数,该函数可以增加一个排序列。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

第一片心意

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值