iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > GO >Golang处理parquet文件实战指南
  • 878
分享到

Golang处理parquet文件实战指南

golang parquetgolang处理parquet文件 2023-03-07 11:03:46 878人浏览 泡泡鱼
摘要

目录前言创建结构体生成parquet文件读取parquet文件计算列平均值总结前言 Parquet是Apache基金会支持的项目,是面向列存储二进制文件格式。支持不同类型的压缩方式,

前言

Parquet是Apache基金会支持的项目,是面向列存储二进制文件格式。支持不同类型的压缩方式,广泛用于数据科学和大数据环境,如hadoop生态。

本文主要介绍Go如何生成和处理parquet文件。

创建结构体

首先创建struct,用于表示要处理的数据:

type user struct {
  ID        string    `parquet:"name=id, type=BYTE_ARRAY, encoding=PLaiN_DICTioNARY"`
  FirstName string    `parquet:"name=firstname, type=BYTE_ARRAY, encoding=PLAIN_DICTIONARY"`
  LastName  string    `parquet:"name=lastname, type=BYTE_ARRAY, encoding=PLAIN_DICTIONARY"`
  Email     string    `parquet:"name=email, type=BYTE_ARRAY, encoding=PLAIN_DICTIONARY"`
  Phone     string    `parquet:"name=phone, type=BYTE_ARRAY, encoding=PLAIN_DICTIONARY"`
  Blog      string    `parquet:"name=blog, type=BYTE_ARRAY, encoding=PLAIN_DICTIONARY"`
  Username  string    `parquet:"name=username, type=BYTE_ARRAY, encoding=PLAIN_DICTIONARY"`
  Score     float64   `parquet:"name=score, type=DOUBLE"`
  CreatedAt time.Time //wont be saved in the parquet file
}

这里要提醒的是tag,用于说明struct中每个字段在生成parquet过程中如何被处理。

parquet-go包可以处理parquet数据,更多的tag可以参考其官网。

生成parquet文件

下面现给出生成parquet文件的代码,然后分别进行说明:

package main

import (
  "fmt"
  "log"
  "time"
  "GitHub.com/bxcodec/faker/v3"
  "github.com/xitongsys/parquet-go-source/local"
  "github.com/xitongsys/parquet-go/parquet"
  "github.com/xitongsys/parquet-go/reader"
  "github.com/xitongsys/parquet-go/writer"
)

type user struct {
  ID        string    `parquet:"name=id, type=BYTE_ARRAY, encoding=PLAIN_DICTIONARY"`
  FirstName string    `parquet:"name=firstname, type=BYTE_ARRAY, encoding=PLAIN_DICTIONARY"`
  LastName  string    `parquet:"name=lastname, type=BYTE_ARRAY, encoding=PLAIN_DICTIONARY"`
  Email     string    `parquet:"name=email, type=BYTE_ARRAY, encoding=PLAIN_DICTIONARY"`
  Phone     string    `parquet:"name=phone, type=BYTE_ARRAY, encoding=PLAIN_DICTIONARY"`
  Blog      string    `parquet:"name=blog, type=BYTE_ARRAY, encoding=PLAIN_DICTIONARY"`
  Username  string    `parquet:"name=username, type=BYTE_ARRAY, encoding=PLAIN_DICTIONARY"`
  Score     float64   `parquet:"name=score, type=DOUBLE"`
  CreatedAt time.Time //wont be saved in the parquet file
}

const recordNumber = 10000

func main() {
  var data []*user
  //create fake data
  for i := 0; i < recordNumber; i++ {
    u := &user{
      ID:        faker.UUIDDigit(),
      FirstName: faker.FirstName(),
      LastName:  faker.LastName(),
      Email:     faker.Email(),
      Phone:     faker.Phonenumber(),
      Blog:      faker.URL(),
      Username:  faker.Username(),
      Score:     float64(i),
      CreatedAt: time.Now(),
    }
    data = append(data, u)
  }
  err := generateParquet(data)
  if err != nil {
    log.Fatal(err)
  }

}

func generateParquet(data []*user) error {
  log.Println("generating parquet file")
  fw, err := local.NewLocalFileWriter("output.parquet")
  if err != nil {
    return err
  }
  //parameters: writer, type of struct, size
  pw, err := writer.NewParquetWriter(fw, new(user), int64(len(data)))
  if err != nil {
    return err
  }
  //compression type
  pw.CompressionType = parquet.CompressionCodec_GZIP
  defer fw.Close()
  for _, d := range data {
    if err = pw.Write(d); err != nil {
      return err
    }
  }
  if err = pw.WriteStop(); err != nil {
    return err
  }
  return nil
}

定义结构体上面已经说明,但需要提醒的是类型与文档保持一致:

Primitive TypeGo Type
BOOLEANbool
INT32int32
INT64int64
INT96(deprecated)string
FLOATfloat32
DOUBLEfloat64
BYTE_ARRAYstring
FIXED_LEN_BYTE_ARRAYstring

接着就是使用faker包生成模拟数据。然后调用err := generateParquet(data)方法。该方法大概逻辑为:

  • 首先准备输出文件,然后基于本地输出文件构造pw,用于写parquet数据:
  fw, err := local.NewLocalFileWriter("output.parquet")
  if err != nil {
    return err
  }
  //parameters: writer, type of struct, size
  pw, err := writer.NewParquetWriter(fw, new(user), int64(len(data)))
  if err != nil {
    return err
  }

  //compression type
  pw.CompressionType = parquet.CompressionCodec_GZIP
  defer fw.Close()

然后设置压缩类型,并通过defer操作确保关闭文件。下面开始写数据:

  for _, d := range data {
    if err = pw.Write(d); err != nil {
      return err
    }
  }
  if err = pw.WriteStop(); err != nil {
    return err
  }
  return nil

循环写数据,最后调用pw.WriteStop()停止写。 成功写文件后,下面介绍如何读取parquet文件。

读取parquet文件

首先介绍如何一次性读取文件,主要用于读取较小的文件:

func readParquet() ([]*user, error) {
  fr, err := local.NewLocalFileReader("output.parquet")
  if err != nil {
    return nil, err
  }

  pr, err := reader.NewParquetReader(fr, new(user), recordNumber)
  if err != nil {
    return nil, err
  }

  u := make([]*user, recordNumber)
  if err = pr.Read(&u); err != nil {
    return nil, err
  }
  pr.ReadStop()
  fr.Close()
  return u, nil
}

大概流程如下:首先定义本地文件,然后构造pr用于读取parquet文件:

  fr, err := local.NewLocalFileReader("output.parquet")
  if err != nil {
    return nil, err
  }

  pr, err := reader.NewParquetReader(fr, new(user), recordNumber)
  if err != nil {
    return nil, err
  }

然后定义目标内容容器u,一次性读取数据:

  u := make([]*user, recordNumber)
  if err = pr.Read(&u); err != nil {
    return nil, err
  }
  pr.ReadStop()
  fr.Close()

但一次性大量记录加载至内存可能有问题。这是官方文档提示:

If the parquet file is very big (even the size of parquet file is small, the uncompressed size may be very large), please don’t read all rows at one time, which may induce the OOM. You can read a small portion of the data at a time like a stream-oriented file.

大意是不要一次读取文件至内存,可能造成OOM。实际应用中应该分页读取,下面通过代码进行说明:


func readPartialParquet(pageSize, page int) ([]*user, error) {
	fr, err := local.NewLocalFileReader("output.parquet")
	if err != nil {
		return nil, err
	}
	defer func() {
		_ = fr.Close()
	}()

	pr, err := reader.NewParquetReader(fr, new(user), int64(pageSize))
	if err != nil {
		return nil, err
	}
	defer pr.ReadStop()

	//num := pr.GetNumRows()
	
	pr.SkipRows(int64(pageSize * page))
	u := make([]*user, pageSize)
	if err = pr.Read(&u); err != nil {
		return nil, err
	}

	return u, nil
}

与上面函数差异不大,首先函数包括两个参数,用于指定页大小和页数,关键代码是跳过一定记录:

  pr.SkipRows(int64(pageSize * page))

根据这个方法可以获得总行数,pr.GetNumRows(),然后结合页大小计算总页数,最后循环可以实现分页查询。

计算列平均值

既然使用了Parquet列存储格式,下面演示下如何计算Score列的平均值。

func calcScoreAVG() (float64, error) {
  fr, err := local.NewLocalFileReader("output.parquet")
  if err != nil {
    return 0.0, err
  }
  pr, err := reader.NewParquetColumnReader(fr, recordNumber)
  if err != nil {
    return 0.0, err
  }
  num := int(pr.GetNumRows())

  data, _, _, err := pr.ReadColumnByPath("parquet_go_root\u0001score", num)
  if err != nil {
    return 0.0, err
  }
  var result float64
  for _, i := range data {
    result += i.(float64)
  }
  return (result / float64(num)), nil
}

首先打开文件,然后调用pr.GetNumRows()方法获取总行数。然后基于路径指定列,其中parquet_go_root为根路径,因为前面使用字节数组,这里分割符变为\u0001,完整路径为:parquet_go_root\u0001score

总结

到此这篇关于golang处理parquet文件的文章就介绍到这了,更多相关Golang处理parquet文件内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: Golang处理parquet文件实战指南

本文链接: https://www.lsjlt.com/news/198779.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Golang处理parquet文件实战指南
    目录前言创建结构体生成parquet文件读取parquet文件计算列平均值总结前言 Parquet是Apache基金会支持的项目,是面向列存储二进制文件格式。支持不同类型的压缩方式,...
    99+
    2023-03-07
    golang parquet golang处理parquet文件
  • Golang如何处理parquet文件
    这篇文章主要介绍“Golang如何处理parquet文件”,在日常操作中,相信很多人在Golang如何处理parquet文件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Golang如何处理parquet文件...
    99+
    2023-07-05
  • Golang实践指南之获取目录文件列表
    目录前言起因实现封装测试及结果扩展优化接口正则表达式带数字的文件名称排序总结前言 获取目录下匹配某种规则的文件,返回文件列表,在开发中比较常用。本文实现此功能,并做了些扩展。 起因 ...
    99+
    2023-01-07
    golang 目录结构 golang获取目录文件列表 golang 遍历目录
  • Python中CSV文件(逗号分割)实战操作指南
    目录一、csv文件介绍1、csv文件简介2、为什么要使用csv文件二、csv文件查看1、测试文件创建2、查看csv文件(列表)3、查看csv文件(字典)4、写入文件(列表)5、写入文...
    99+
    2022-11-11
  • python数据分析实战指南之异常值处理
    目录异常值1、异常值定义2、异常值处理方式2.1 均方差2.2 箱形图3、实战3.1 加载数据3.2 检测异常值数据3.3 显示异常值的索引位置总结异常值 异常值是指样本中的个别值,...
    99+
    2022-11-13
  • Linux文件操作的必备技能——GO语言开发实战指南
    在Linux系统下,文件操作是一项必备技能。而GO语言是一门非常适合文件操作的语言。本文将介绍GO语言开发实战指南,帮助您学习如何使用GO语言进行Linux文件操作。 一、文件的创建与删除 在GO语言中,我们可以使用os包中的Create...
    99+
    2023-10-02
    开发技术 linux 文件
  • Shell脚本与Java的完美结合:数组和文件操作实战指南!
    Shell脚本和Java是两种非常常用的编程语言,它们各自有着不同的应用场景和优势。然而,在实际项目中,我们可能需要将这两种语言结合起来使用,以充分发挥它们的优势和实现更强大的功能。本文将介绍Shell脚本和Java的完美结合,特别是在数组...
    99+
    2023-10-31
    shell 数组 文件
  • 文件处理困扰你?看这篇 Java 大数据开发指南!
    在大数据处理过程中,文件处理是一个非常重要的环节。无论是数据采集、数据清洗还是数据分析,都离不开文件处理。然而,文件处理往往是一个耗时、耗资源的过程,特别是在数据量很大的情况下。为了更好地处理大数据文件,我们可以利用 Java 的强大功能...
    99+
    2023-06-20
    大数据 文件 ide
  • Java并发编程实战:高效处理大量文件
    在现代计算机应用程序中,处理大量文件是一项常见的任务。处理大量文件的一个主要挑战是确保程序在处理文件时能够高效地利用计算机的多核处理能力。Java并发编程提供了一种优雅的方式来处理这个问题。在本文中,我们将介绍Java并发编程的一些基础知...
    99+
    2023-10-17
    并发 响应 文件
  • 从路径分隔符到文件名处理:PHP、Unix和Bash的路径操作指南
    路径处理是编程中经常需要处理的一项任务,它涉及到文件系统中文件和目录的访问和操作。在本文中,我们将介绍PHP、Unix和Bash中的路径操作指南,包括路径分隔符、路径格式化、文件名处理等。 一、路径分隔符 路径分隔符是用于分隔不同路径段的...
    99+
    2023-10-14
    unix bash path
  • 《Oracle 12c 运维实战宝典》-参数文件管理与无备份坏块处理分享
    《Oracle 12c 运维实战宝典》-参数文件管理与坏块处理分享 链接:https://pan.baidu.com/s/1gbuLk8wLX4pk68mDylxGEg 密码:ohtl ...
    99+
    2022-10-18
  • 如何使用批处理实现全盘搜索指定文件并拷贝到指定位置
    小编给大家分享一下如何使用批处理实现全盘搜索指定文件并拷贝到指定位置,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!代码如下:@echo off&setlocal enabledelayedexp...
    99+
    2023-06-08
  • 批处理bat如何实现全盘搜索指定文件获取其完整路径
    小编给大家分享一下批处理bat如何实现全盘搜索指定文件获取其完整路径,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!想用的话,自己保存成bat文件即可。【方案一】f...
    99+
    2023-06-08
  • 批处理bat如何实现下载FTP服务器上指定天数之前的文件
    这篇文章主要介绍了批处理bat如何实现下载FTP服务器上指定天数之前的文件,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。示例代码:@echo offrem ...
    99+
    2023-06-08
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作