Apache Arrow Parquet存储与使用

 更新时间:2023年08月30日 09:14:55   作者:龚正阳  
这篇文章主要为大家介绍了Apache Arrow Parquet存储与使用原理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

简介

Parquet是一种高效的列式存储格式,广泛用于大数据系统中的数据仓库和数据管理工具中,旨在提高数据分析的性能和效率,能够更好地支持数据压缩和列式查询,同时兼顾读写速度和数据大小

初衷

为了让 Hadoop 生态系统中的任何项目都能利用压缩、高效的列式数据表示的优势

技术与原理

基于列存储和压缩技术,每一列的数据通过一系列压缩算法进行压缩,然后存储到文件系统中,这种方式能够避免存储冗余数据,并且能够使查询只涉及到所需的列,从而大大提高查询效率

相关术语

  • Blockhdfs Block):hdfs中的数据块
  • Filehdfs 文件,包含文件的元数据,不需要包含实际的数据
  • Row group/行组:将数据水平划分为Row group
  • Column chunk:特定列的数据块,它们位于特定的行组中,并保证在文件中是连续的
  • Page:列块被分为页,页面在概念上是一个不可分割的单元(就压缩和编码而言),列块中可以有多种交错的页面类型,Page为了让数据读取的粒度足够小,便于单条数据或小批量数据的查询

从层次结构上看,文件由一个或多个行组组成,行组的每列恰好包含一个列块,列块包含一页或多页

结构图如下

文件格式如下

4-byte magic number "PAR1"
<Column 1 Chunk 1 + Column Metadata>
<Column 2 Chunk 1 + Column Metadata>
...
<Column N Chunk 1 + Column Metadata>
<Column 1 Chunk 2 + Column Metadata>
<Column 2 Chunk 2 + Column Metadata>
...
<Column N Chunk 2 + Column Metadata>
...
<Column 1 Chunk M + Column Metadata>
<Column 2 Chunk M + Column Metadata>
...
<Column N Chunk M + Column Metadata>
File Metadata
4-byte length in bytes of file metadata
4-byte magic number "PAR1"

Header

Header的内容很少,只有4个字节,本质是一个magic number,用来指示文件类型

PAR1:普通的Parquet文件

PARE: 加密过的Parquet文件

File Body

实际存储数据,包含Column ChunkColumn Metadata

Footer

  • 包含了诸如schemaBlockoffsetsizeColumn Chunkoffsetsize等所有重要的元数据
  • 承担了整个文件入口的职责,读取Parquet文件的第一步就是读取Footer信息,转换成元数据之后,再根据这些元数据跳转到对应的blockcolumn,读取真正所要的数据

Index

IndexParquet文件的索引块,主要为了支持谓词下推(Predicate Pushdown)功能

谓词下推是一种优化查询性能的技术,简单地来说就是把查询条件发给存储层,让存储层可以做初步的过滤,把肯定不满足查询条件的数据排除掉,从而减少数据的读取和传输量

Parquet索引类型

  • Max-MinMax-Min索引是对每个Page都记录它所含数据的最大值和最小值,这样某个Page是否不满足查询条件就可以通过这个Pagemaxmin值来判断
  • BloomFilter索引: 针对value比较稀疏,max-min范围比较大的列,用Max-Min索引的效果就不太好,BloomFilter可以克服这一点,同时也可以用于单条数据的查询

rust读写Parquet文件

依赖项目

https://github.com/apache/arrow-r

修改Cargo.toml如下

[dependencies]
parquet = "46.0.0"
parquet_derive = "46.0.0"

修改main.rs

use std::convert::TryFrom;
use std::{fs, path::Path};
use parquet::file::reader::SerializedFileReader;
use parquet::file::writer::SerializedFileWriter;
use parquet::record::RecordWriter;
use parquet_derive::ParquetRecordWriter;
const PARQUET_FILEPATH: &str = "./target/sample.parquet";
#[derive(ParquetRecordWriter)]
struct ACompleteRecord<'a> {
    pub a_bool: bool,
    pub a_str: &'a str,
}
fn write() {
    let path = Path::new(PARQUET_FILEPATH);
    let file = fs::File::create(path).unwrap();
    let samples = vec![
        ACompleteRecord {
            a_bool: true,
            a_str: "I'm true",
        },
        ACompleteRecord {
            a_bool: false,
            a_str: "I'm false",
        },
    ];
    let schema = samples.as_slice().schema().unwrap();
    let mut writer = SerializedFileWriter::new(file, schema, Default::default()).unwrap();
    let mut row_group = writer.next_row_group().unwrap();
    samples
        .as_slice()
        .write_to_row_group(&mut row_group)
        .unwrap();
    row_group.close().unwrap();
    writer.close().unwrap();
}
fn read() {
    let rows = [PARQUET_FILEPATH]
        .iter()
        .map(|p| SerializedFileReader::try_from(*p).unwrap())
        .flat_map(|r| r.into_iter());
    for row in rows {
        println!("{}", row.unwrap());
    }
}
fn main() {
    write();
    read();
}

运行

$ cargo run   
   Compiling temp v0.1.0 (/home/gong/rust-work/temp)
    Finished dev [unoptimized + debuginfo] target(s) in 2.26s
     Running `target/debug/temp`
{a_bool: true, a_str: "I'm true"}
{a_bool: false, a_str: "I'm false"}

查看parquet文件

$ cat target/sample.parquet
PAR1,X%a_bool44<X22I'm true     I'm false,I'm true      I'm false
                                                                 5a_str��&�&�I'm true   I'm false       I'm falsI'm tru4�V<H
     rust_schema%a_bool
                       %a_str%L,&<%a_bool44<X��"&�
                                                  5a_str��&�&�I'm true  I'm false��@��(parquet-rs version 46.0.0�PAR1%

阅读参考

Apache parquet document

详解Parquet文件格式原理

以上就是Apache Arrow Parquet存储与使用的详细内容,更多关于Apache Arrow Parquet存储的资料请关注脚本之家其它相关文章!

相关文章

  • Zookeeper Curator使用介绍

    Zookeeper Curator使用介绍

    curator是Netflix公司开源的⼀套Zookeeper客户端框架,和ZKClient⼀样,Curator解决了很多Zookeeper客户端非常底层的细节开发⼯作,包括连接重连,反复注册Watcher和NodeExistsException异常等,是最流行的Zookeeper客户端之⼀
    2022-09-09
  • java中的PriorityQueue类过程详解

    java中的PriorityQueue类过程详解

    这篇文章主要介绍了java中的PriorityQueue类,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • 解决jpa查询语句自动变成了update的问题

    解决jpa查询语句自动变成了update的问题

    这篇文章主要介绍了解决jpa查询语句自动变成了update的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Java 程序初始化顺序

    Java 程序初始化顺序

    这篇文章主要介绍了Java 程序初始化顺序,在Java语言中,当实例化对象时,对象所在类的所有成员变量首先要进行初始化,只有当所有的类成员完成了初始化之后,才会调用对象所在类的构造函数创建对象,需要的朋友可以参考一下
    2022-01-01
  • Collections工具类_动力节点Java学院整理

    Collections工具类_动力节点Java学院整理

    Collections工具类提供了大量针对Collection/Map的操作。这篇文章主要介绍了Collections工具类_动力节点Java学院整理,需要的朋友可以参考下
    2017-04-04
  • log4j2采用AsyncLogger出现的错误及解决方案

    log4j2采用AsyncLogger出现的错误及解决方案

    这篇文章主要介绍了log4j2采用AsyncLogger出现的错误及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • OpenFeign服务接口调用的过程详解

    OpenFeign服务接口调用的过程详解

    Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单。它的使用方法是定义一个服务接口然后在上面添加注解,这篇文章主要介绍了OpenFeign服务接口调用,需要的朋友可以参考下
    2022-10-10
  • SpringMVC中解决@ResponseBody注解返回中文乱码问题

    SpringMVC中解决@ResponseBody注解返回中文乱码问题

    这篇文章主要介绍了SpringMVC中解决@ResponseBody注解返回中文乱码问题, 小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • 详解Java的文件与目录管理以及输入输出相关操作

    详解Java的文件与目录管理以及输入输出相关操作

    这篇文章主要介绍了详解Java的文件与目录管理以及输入输出相关操作,是Java入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • JavaSwing BorderLayout 边界布局的实现代码

    JavaSwing BorderLayout 边界布局的实现代码

    这篇文章主要介绍了JavaSwing BorderLayout 边界布局的实现代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12

最新评论