Hive分区表数据压缩

news2024/11/25 0:50:59

Hive分区表数据压缩

1.背景

目前公司的Hive分区表采用的TextFile格式存储,占用的存储空间较大,考虑到存储成本,需要对存储的历史数据进行压缩。

2.压缩格式选择

2.1 snappy压缩

优点:高速压缩速度和合理的压缩率;支持Hadoop native库。

缺点:不支持split;压缩率比gzip要低;Hadoop本身不支持,需要安装;linux系统下没有对应的命令。

应用场景:当MapReduce作业的map输出的数据量比较大的时候,作为map到reduce的中间数据的压缩格式;或者作为一个MapReduce作业的输出和另外一个MapReduce作业的输入。

2.2 lzo压缩

优点:压缩/解压速度也比较快,合理的压缩率;支持split,是Hadoop中最流行的压缩格式;支持Hadoop native库;可以在linux系统下安装lzop命令,使用方便。

缺点:压缩率比gzip要低一些;hadoop本身不支持,需要安装;在应用中对lzo格式的文件需要做一些特殊处理(为了支持split需要建索引,还需要指定inputformat为lzo格式)。

应用场景:一个很大的文本文件,压缩之后还大于200M以上的可以考虑,而且单个文件越大,lzo优点越明显。

2.3 gzip压缩

优点:压缩率比较高,而且压缩/解压速度也比较快;Hadoop本身支持,在应用中处理gzip格式的文件就和直接处理文本一样;有Hadoop native库;大部分linux系统都自带gzip命令,使用方便。

缺点:不支持split

应用场景:当每个文件压缩之后在130M以内的,都可以考虑用gzip压缩格式。比如每天的日志压缩成一个gzip文件,运行MapReduce程序的时候通过多个gzip文件达到并发。对于处理这些文件的程序(如Hive、流、MapReduce程序)完全和文本处理一样,压缩之后原来的程序不需要做任何修改。

2.4 bzip2压缩

优点:支持split;具有很高的压缩率,比gzip压缩率都高;Hadoop本身支持,但不支持native;在linux系统下自带bzip2命令,使用方便。

缺点:压缩/解压速度慢;不支持native。

应用场景:适合对速度要求不高,但需要较高的压缩率的场景。可以作为MapReduce作业的输出格式;输出之后的数据比较大,处理之后的数据需要压缩存档减少磁盘空间并且以后数据用得比较少的情况;对单个很大的文本文件想压缩减少存储空间,同时又需要支持split,而且兼容之前的应用程序(即应用程序不需要修改)的情况。

PS: 由于是对历史数据进行压缩,因此选择了Hadoop原生兼容以及压缩比较高且支持split的bzip2压缩算法。

2.5 查看当前集群支持的压缩编码

目前公司使用的CDH集群,在HDFS服务的配置中搜索io.compression.codecs即可查看当前Hadoop支持的压缩编码格式,如下图所示,org.apache.hadoop.io.compress.BZip2Codec就是Bzip2压缩格式的编码解码器,如果没有加上配置,重启服务即可。
在这里插入图片描述

3.代码实现

Hive的分区表数据存放在HDFS上,并且存放数据的目录是最内层一级的分区,因此使用Spark和HDFS客户端对文件进行压缩,具体实现思路如下。

  • 首先接受一个分区路径,这个路径是最内层一级分区的上一级分区路径
  • 遍历当前分区下的所有路径,这个路径就是数据存放的路径
  • 读取数据存放路径中的数据,使用Spark Core的saveAsTextFile指定输出格式为Bzip2对数据进行压缩输出到当前路径下临时路径中。
  • 删除原来分区路径下的数据,将临时路径中压缩好的数据移动到原来分区路径,这样就完成一个分区的数据压缩
  • 循环完成就完成了一个一级分区的所有二级分区的压缩
  • 最后删除临时路径,完成数据压缩

代码如下所示

public class Text2Bzip {

    public static void main(String[] args) throws IOException {
        // 创建SparkContext
        SparkConf sparkConf = new SparkConf();
        sparkConf.setAppName("test_bizip2");
        JavaSparkContext sc = new JavaSparkContext(sparkConf);
        // 获取路径
        String path = args[0];
        // 获取hdfs客户端
        Configuration hadoopConf = new Configuration();
        FileSystem fs = FileSystem.get(hadoopConf);
        // 遍历当前压缩分区的文件
        RemoteIterator<LocatedFileStatus> iterator = fs.listLocatedStatus(new Path(path));
        while (iterator.hasNext()) {
            Path dataPath = iterator.next().getPath();
            String tempPath = path + "/compression/" + dataPath.getName();
            System.out.println("=======================>");
            System.out.println("开始处理: ");
            System.out.println("压缩数据目录: " + dataPath);
            System.out.println("临时目录: " + tempPath);
            // 获取并行度
            int parallelize = getParallelize(fs, dataPath.toString());
            if (parallelize == -1) {
                System.out.println("没有文件!");
            } else {
                // 执行压缩
                zip(sc, dataPath.toString(), tempPath, parallelize);
                // 移动文件
                mv(fs, tempPath, dataPath.toString());
            }
        }
        // 删除临时目录
        fs.delete(new Path(path + "/compression/"), true);
        // 停止Spark程序
        sc.stop();
    }

    // 压缩
    public static void zip(JavaSparkContext sc, String src, String temp, int parallelize) {
        System.out.println("-----------zip-----------------");
        sc.textFile(src).coalesce(parallelize).saveAsTextFile(temp, BZip2Codec.class);
    }

    // 获取并行度
    public static int getParallelize(FileSystem fs, String path) throws IOException {
        RemoteIterator<LocatedFileStatus> iterator = fs.listFiles(new Path(path), false);
        long size = 0L;
        while (iterator.hasNext()) {
            size += iterator.next().getLen();
        }
        if (size == 0) {
            return -1;
        } else {
            // 控制每个task 读取256MB的文件 减少小文件
            return (int) (size / 268435456) + 1;
        }
    }

    // 移动文件
    public static void mv(FileSystem fs, String src, String dst) throws IOException {
        Path dstPath = new Path(dst);
        Path srcPath = new Path(src);
        fs.delete(dstPath, true);
        fs.mkdirs(dstPath);
        RemoteIterator<LocatedFileStatus> iterator = fs.listFiles(srcPath, false);
        while (iterator.hasNext()) {
            LocatedFileStatus file = iterator.next();
            fs.rename(file.getPath(), new Path(dstPath, file.getPath().getName()));
        }
    }
}

由于Hadoop原生支持Bzip2压缩算法,因此,不会影响到Hive正常读取,但是读取速度相比之前可能会慢一些。

4.效果

通过观察Spark的WebUI,如下图所示,可以看到输入的数据为4GB左右,压缩后输出的数据为80MB左右,压缩比在50倍左右,当然这也与数据的分布规律有关。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/52553.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java - 数据结构,顺序表

1、顺序表和链表都属于数据结构的一部分。 2、数据结构:C的数据结构和JAVA的数据结构有什么不一样啊? 数据结构只是一个单独的学科&#xff0c;和语言没有关系。 用不同的语言实现一样的逻辑。 一、线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据…

如何使用远程Linux虚拟机的图形界面

博客主页&#xff1a;https://tomcat.blog.csdn.net 博主昵称&#xff1a;农民工老王 主要领域&#xff1a;Java、Linux、K8S 期待大家的关注&#x1f496;点赞&#x1f44d;收藏⭐留言&#x1f4ac; 目录VMware Workstation ProSmarTTY在工作过程中&#xff0c;有时需要操作远…

微机----------LED显示接口

目录 LED显示器的工作原理采用专用芯片进行LED段译码软件译码法静态显示与动态显示LED显示器的工作原理 LED显示器的主要部分是七段发光管,这七段发光段分别称为a、b、c、d、e、f、g有的产品还附带有一个小数点DP。通过7个发光段的组合,可以显示0 ~ 9 和 A ~ F共16个字母数字…

果然AIGC还是对动漫制作下手了,不过是从数据集AnimeRun开始

原文链接&#xff1a;https://www.techbeat.net/article-info?id4327 作者&#xff1a;seven_ 最近AIGC领域的新工作几乎呈现一种井喷式的发展&#xff0c;借助AI模型天马行空的想象力&#xff0c;研究者们开始在各种图像和视频内容领域发力&#xff0c;本文介绍一篇发表在Neu…

MybatisPlus 处理保存实体对象时,对于枚举类型的数据库存储问题

MybatisPlus 处理保存实体对象时&#xff0c;对于枚举类型的数据库存储问题1. 前言1.1 先看问题代码1.2 存在的问题2. 解决前言问题2.1 自定义枚举2.2 附源码&#xff1a;3. 参考4. 推荐 Mybatis、MybatisPlus 其他相关问题的文章1. 前言 1.1 先看问题代码 如下&#xff1a;枚…

告别人工叫号!门诊排队叫号系统,这样配置,性价比高

很多人认为&#xff0c;那些大医院的叫号系统&#xff0c;确实既高效便捷、又能展现门诊综合服务实力。 但安装配置较为复杂&#xff0c;内部软件与硬件对接存在难度&#xff0c;价格也相对昂贵&#xff0c;对部分医院来讲&#xff0c;预算稍有不足&#xff0c;怎么办&#xff…

serverless-OpenWhisk安装

1.安装 默认我们已经有了一个k8s集群&#xff0c;采用helm方式安装。以下操作均在 Master 节点执行。 helm要求Helm v3.2.0或以上版本。 多节点worker打标签 如果要将OpenWhisk部署到具有多个工作节点的群集&#xff0c;我们建议使用节点关联将用于OpenWhisk控制平面的计算节点…

【论文阅读笔记】Pyramid Real Image Denoising Network

论文简介 本文是19年的论文&#xff0c;网络名为PRIDNet。代码地址为https://github.com/491506870/PRIDNet。在1080ti上&#xff0c;PRIDNet处理512x512图像需要大约50ms&#xff1b; 尽管深度卷积神经网络在特定噪声和去噪方面展示出非凡能力&#xff0c;但对于真实世界的噪声…

最好的天线基础知识!超实用 随时查询

天线作为无线电的发射和接收设备是影响信号强度和质量的重要设备,其在移动通信领域的重要性非常关键。通过对天线选型,天线安装,天线调整从而保障基站覆盖区域的信号强度与质量。对其的 掌握程度是网规与网优工程师的技能基本要求之一。下文重点说明天线要掌握哪些方面及其原理…

jenkins配置钉钉机器人推送job构建信息

文章目录一、注册钉钉&#xff0c;创建群聊二、创建钉钉机器人&#xff0c;获取webhook三、jenkins安装DingTalk插件四、jenkins系统配置—配置钉钉1、找到钉钉配置项&#xff0c;继续配置五、jenkins的job内配置钉钉六、构建job&#xff0c;并发送钉钉信息推送Q & A一、注…

[iOS]App Store Connect添加银行卡时的CNAPS代码查询

App Store Connect 协议、税务和银行业务中&#xff0c;给付费APP类型添加银行卡需要填写CNAPS代码CNAPS代码&#xff0c;其实就是联行号。 联行号又称大额行号、银联号、银行行号或CNAPS号。 银行联行号查询

JavaScript -- 06.函数知识汇总

文章目录函数1 函数介绍2 函数的创建方式2.1 函数声明2.2 函数表达式2.33 参数3.1 函数声明3.2.函数表达式3.3 箭头函数3.4 默认参数3.5 使用对象作为参数3.6 函数作为参数4 函数的返回值5 作用域5.1 函数作用域5.2 作用域链5.3 练习6 window对象7 提升7.1 变量的提升7.2 函数的…

【深度学习】详解 ViLT

目录 摘要 一、引言 二、背景 2.1 视觉和语言模型的分类法 2.2 模态交互模式 2.3 视觉嵌入方案 2.3.1 区域特征 2.3.2 网格特征 2.3.3 图像块投影 三、视觉和语言 Transformer 3.1 模型概述 3.2 预训练目标 3.2.1 图像文本匹配 3.2.2 掩码语言建模 3.2.3 全…

文件包含漏洞详解

文件包含漏洞详解1.文件包含漏洞介绍1.1.文件包含漏洞解释1.2.文件包含漏洞原理1.3.文件包含的函数1.3.1.常见的文件包含函数1.3.2.PHP函数区别&#xff1a;1.4.文件包含漏洞特征1.5.文件包含漏洞分类1.5.1.本地文件包含漏洞  1.5.1.1.本地文件包含漏洞案例1.5.2.远程文件包含…

echarts-wordcloud ——文字云制作企业标签——基础积累

最近看到同事在写文字云的效果&#xff0c;最终效果图如下&#xff1a; 使用的是echarts-wordcloud插件&#xff1a; 下面介绍一下使用步骤&#xff1a; 1.npm安装echarts-wordcloud——npm install echarts-wordcloud --save 安装echarts-wordcloud的前提是也要安装echart…

谷粒学院——Day09【整合阿里云视频点播】

❤ 作者主页&#xff1a;Java技术一点通的博客 ❀ 个人介绍&#xff1a;大家好&#xff0c;我是Java技术一点通&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 记得关注、点赞、收藏、评论⭐️⭐️⭐️ &#x1f4e3; 认真学习&#xff0c;共同进步&#xff01;&am…

YOLOv5使用方法记录

YOLOv5使用方法记录 本次主要是记录使用yolov5检测图片和视频的过程 下载源码 地址为&#xff1a;https://github.com/ultralytics/yolov5 配置环境 有两种方法 按照requirements 通过下述命令安装源码中给出的配置环境文件 pip install -r requirements.txt选择自己需…

诠释韧性增长,知乎Q3财报里的社区优势和商业化价值

当内容平台开始做生意&#xff0c;往往意味着它要扮演一个大包大揽的角色&#xff1a;从内容的可持续性到最终变现&#xff0c;设计一套完整的生态系统是必需的。 但并非所有平台都对此感到棘手&#xff0c;或者说在某些平台&#xff0c;生态已经不是困难&#xff0c;而是优势…

linux内核源码分析 - nvme设备的初始化

驱动的加载 驱动加载实际就是module的加载,而module加载时会对整个module进行初始化,nvme驱动的module初始化函数为nvme_init(),如下: static struct pci_driver nvme_driver {.name "nvme",.id_table nvme_id_table,.probe nvme_probe,.remo…

leetcode 746. 使用最小花费爬楼梯

文章目录题目思考代码和注释总结题目 给你一个整数数组 cost &#xff0c;其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用&#xff0c;即可选择向上爬一个或者两个台阶。 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。 请你计算并返回达到…