目录

Parquet是什么

为什么使用Parquet

Parquet为什么快

如何使用Parquet

Best Practice

Reference


Parquet是什么

Parquet是一种为了对表格型数据实现高性能IO所设计的数据文件格式,其使用高效的压缩算法和数据编码方式,实现数据的精简,从而减少数据IO,同时提高性能。其同时是开源的,多种语言都实现了Parquet的包,可以直接使用,比如python。

为什么使用Parquet

Parquet因为其出色的IO性能,受到了广泛的使用,并且越来越流行。其适合作为存储大量的原始数据,作为数据湖的基本数据格式,因为其不仅有出色的IO性能,同时也需要很少的磁盘空间。博主用Parquet和CSV以及HDF5做过对比,对于相同的数据,无论是IO性能还是磁盘空间,Parquet都显著由于CSV和HDF5,尤其相对于CSV,Parquet默认的压缩算法只使用了CSV四分之一的空间,而且数据读取性能可以提升200倍左右(仅是博主自己的测试数据,可能还更高)。而且相比于feather这种轻量级的数据格式,Parquet在IO性能和空间占用也毫不逊色,更关键的是,Parquet还可以使用数据集(Dataset)功能实现层级数据管理,以及读取时的数据行和列的过滤功能,不失灵活性。

此外,数据格式是独立的,不依赖任何的编程语言,即同一个Parquet文件,可以用不同的编程语言的相应的库直接使用,从而利于数据的分享。

Parquet为什么快

Parquet的高性能源于其独特的数据结构、存储方式、数据编码和压缩算法。

Parquet采用网格方式存储数据。数据存储方式有列向、行向以及网格,列向存储把同列数据放在连续的磁盘空间中,因此对列的过滤读取是相对高效的;同理,行向存储把同一行的数据保存在磁盘的连续空间中,因此对行的过滤读取相对高效;Parquet是网格存储,即先将一定大小的行作为一个row group,然后这个row group中的每列作为一个column chunk,逐个column chunk存储,同时Parquet使用了metadata,用以描述数据,可以更加高效的对数据进行处理和解析。

图片来自[4]

Parquet还使用了字典编码,以及RLE编码(Run Length Encoding),将数据值映射成数字,然后保存一个字典映射,同时记录某个值连续重复的次数,这样不用反复的保存一些占用空间较大的数据,特别是对于字符类型的数据,这种方式尤其对于重复值较多的chunk,非常高效,实际上我们的表格数据经常某些列具有较多的重复数据。因此,Parquet的这些编码方式,可以高效的节省空间,减少实际数据的IO,但是需要更多的metadata的解析,将IO密集部分变成了CPU密集的工作,CPU当然快多了。这些是Parquet如此高效的根本原因。

如何使用Parquet

Pandas实现了parquet的读写接口,可以直接读取和写入生成parquet文件。Pandas对parquet的接口相对简单,更多的功能需要去相应的引擎库中找到对应接口,具有丰富的功能。pandas对parquet接口的实现基于pyarrow引擎或者fastparquet,可以通过engine参数设置。博主安装的是pyarrow引擎,直接pip install pyarrow即可安装parquet引擎,然后便可以直接通过pandas的数据接口实现parquet的读写的,具体可以看pandas官方文档,见[2]。

这里特别强调一下,对于pyarrow引擎,pandas的读写基于pyarrow的write_table、write_to_dataset和read_table实现,因此可以参考这两个接口,实现更多的功能,比如通过read_table的filters参数,实现读取过滤,该参数可以直接通过pandas的read_parquet函数传入。具体使用方法参见[1]。

Best Practice

1. 读取parquet文件时,虽然可以使用python通过open返回的fileobject对象,但是尽量避免使用,会显著的降低IO性能,直接使用字符路径即可。

2. Parquet读取文件时,需要先对数据进行解析,无法直接使用memory map,因此并没有明显的内存改善,但是在有些系统中可以提升性能。

3. Parquet利用字典编码和RLE提升性能,但是数据量太大,以及非重复值太多,导致字典太大,超出阈值,就会使得剩下的数据直接只用plain encoding,即对数据本身逐一的编码,没有字典和RLE的优化,这时就会导致读写性能降低,磁盘空间也无法节省。对此,可以通过write_table的dictionary_page_size参数提高字典大小的限制,或者降低row_group_size,从而降低column chunk,使得单个字典编码的数据量减少。

4. 由于metadata会保存每个column chunk的min max count属性,在读取时进行行过滤(predict)时,parquet通过metadata记录的这些信息预先判断相应的group中有无目标数据,若没有就直接跳过,都不需要解析扫描这些group,从而可以显著的提高性能。基于此特点,在写入数据时,就应该先对会被经常拿来过滤数据的column进行排序,排序后再保存,这样可以使得chunk的range更小,从而最大的减少被解析扫描的数据,提高读取性能。

5. 充分利用partition。parquet最好不要太大,对于大数据集,可以使用partition_cols,传入列名,就会对这个数据集根据指定的列进行拆分,比如指定日期date,就会根据日期,在指定的文件路径下生成多个名称为date=YYYY-mm-dd的文件夹,文件夹里面存放文件名不重复的md5码parquet文件,如果指定了多列,就会以嵌套文件夹的同样命名方式保存parquet文件。这样的文件结构成为parquet dataset,假设写入时的路径参数为/data/xxx,那么在/data/xxx下就会生成多个上述文件夹和文件,/data/xxx就称为一个parquet dataset。在读取时,同样只要传入/data/xxx即可,parquet会自动通过文件夹名称识别过滤相应的文件。因为文件被拆分,可以减少数据解析和扫描,以及metadata的缘故,dataset方式可以显著提升查询IO性能。但是同时要避免太多的小文件,小文件太多,拆分太随意,毕竟每个parquet具有必要的结构,创建每个文件都有最低的开销overhead,文件太多拆分太随意,反而会增加负担,降低性能。一般单个文件几十上百兆到1Gb以下都是没问题的,甚至dataset中文件不多的情况下,单个文件几个Gb对parquet来说也是绰绰有余的,当然具体也和硬件配置有关。

6. 对于partitioned dataset,在read的时候,其中用来分隔数据集的partition_cols会转为Arrow dictionary types (pandas categorical),for some reasons,这会使得在读取时列不保序。因此对于partitioned dataset,不能预期保存和读取的数据行的顺序是一致的。如果要使得读取和保存的时候顺序一致,可以在保存数据的时候,设置数据的index为顺序索引,并设to_parquet的参数index=True,然后读取数据后,对读取后的dataframe的索引进行排序sort_index。

7. 对于pandas.DataFrame的object列,如果类型为object的列包含了np.nan值,那么parquet对于这种情况下的nan值的读写结果是不一样的。当将这种情况下的数据保存成parquet后,再读取成DataFrame后,之前的nan值会变成None,不再是nan,这点需要格外注意,因为变成None后,空值从float类型变成了None类型,可能在有些场景会不兼容(pandas对于把None也当中NaN处理,所以isna fillna等函数对None依然work),需要将None转回nan值才可。当然也可以将read_parquet的use_nullable_dtypes参数设为True,默认是False,这样会将缺失值用pd.NA替代,而不是None,但是风险在于这个参数只是实验性的,在pandas的后续版本可能随时会发生改变。

Reference

[1] Reading and Writing the Apache Parquet Format — Apache Arrow v9.0.0

[2] IO tools (text, CSV, HDF5, …) — pandas 1.5.0 documentation

[3] ​​​​​​https://www.youtube.com/watch?v=1j8SdS7s_NY&ab_channel=Databricks

[4] https://towardsdatascience.com/demystifying-the-parquet-file-format-13adb0206705

高效数据存储格式Parquet相关推荐

  1. Hive(数据仓库)数据压缩、数据存储格式

    7.hive的数据压缩 在实际工作当中,hive当中处理的数据,一般都需要经过压缩,前期我们在学习hadoop的时候,已经配置过hadoop的压缩,我们这里的hive也是一样的可以使用压缩来节省我们的 ...

  2. Hive的数据存储格式

    Hive支持的存储数据的格式主要有: Hive支持的存储数据的格式主要有 存储形式 TEXTFILE 行式存储 SEQUENCEFILE 行式存储 ORC 列式存储 PARQUET 列式存储 列式存储 ...

  3. SamplePairing:针对图像处理领域的高效数据增强方式 | PaperDaily #34

    在碎片化阅读充斥眼球的时代,越来越少的人会去关注每篇论文背后的探索和思考. 在这个栏目里,你会快速 get 每篇精选论文的亮点和痛点,时刻紧跟 AI 前沿成果. 点击本文底部的「阅读原文」即刻加入社区 ...

  4. HBase数据存储格式

    好的数据结构,对于检索数据,插入数据的效率就会非常高. 常见的数据结构 B+树 根节点和枝节点很简单,分别记录每个叶子节点的最小值,并用一个指针指向叶子节点.  叶子节点里每个键值都指向真正的数据块, ...

  5. 高效数据序列化的工具 FlatBuffers 的初体验

    2019独角兽企业重金招聘Python工程师标准>>> 1. 背景 最近在项目中需要使用一种高效数据序列化的工具.碰巧在几篇文章中都提到了FlatBuffers 这个库.特别是 An ...

  6. TFRecord —— tensorflow 下的统一数据存储格式

    tensorflow 提供了统一的数据存储格式,即 TFRecord(record 表示记录),以提高程序的可扩展性,当数据来源十分复杂时,仍能有效记录输入数据中的信息. 1. tfrecord 使用 ...

  7. 常用数据存储格式之xml

    常用数据存储格式介绍 XML 被设计用来传输和存储数据,其焦点是数据的内容. HTML 被设计用来显示数据,其焦点是数据的外观. 语法规则: XML 文档必须有一个根元素 XML元素都必须有一个关闭标 ...

  8. 高效数据同步工具DataX的使用

    一.DataX 简介 DataX 是阿里云 DataWorks 数据集成 的开源版本,主要就是用于实现数据间的离线同步. DataX 致力于实现包括关系型数据库(MySQL.Oracle 等).HDF ...

  9. h5py数据存储格式与图像加载

    h5py数据存储格式 h5py是python中一种数据压缩格式,它的优势:速度快.压缩效率高.尤其是在处理深度学习的大量图像时,常常用到. h5py 的写入与读取 import h5py import ...

最新文章

  1. H5新增的标签以及属性
  2. Android蓝牙4.0的数据通讯
  3. 系统新模块增加需要哪些步骤_在1769系统里使用MVI69MCM的有福了
  4. Manuscript match— 找到最适合你文章的那个ta(之期刊杂志)
  5. netsh winsock reset什么意思_IOS14.2rc是什么意思?ios14.2rc怎么样?[多图]-手机资讯...
  6. [Git] GitHub 上使用 md 的几点问题
  7. 计算机网络四级题库word,计算机四级考试题库2016
  8. 关于缩短编写代码数据花费时间的问题
  9. HDU2109 Fighting for HDU【排序】
  10. (暴力求解)百钱买百鸡问题升级版
  11. 数乌龟(母牛,兔子....)[打表法]
  12. libiconv android编译,(OK) 编译libiconv-1.14(静态库)—CentOS 7— android-ndk
  13. TransCAD划分交通小区及求PA的问题
  14. 博士后到底值不值得做?!
  15. win10可以上网但显示无法连接到Internet
  16. 【图像增广库imgaug】官方文档翻译(一):加载并增强图片
  17. nested exception is com.google.gson.JsonSyntaxException: com.google.gson.stream-异常解决!!!
  18. 不换行输出的两种方式
  19. r329开发板部署aipu模型
  20. iOS 15Beta5版本更新变化,这些细节你发现了吗?

热门文章

  1. 更换Ubuntu默认源为国内源
  2. 基于Linux的c语言知识
  3. 移动通信产业发展超越预期,5GtoB生态圈生机勃勃
  4. Mysql 查询满足条件 相邻的两条数据(场景:上一篇、下一篇)
  5. 软件项目管理 7.4.4.进度计划编排-资源优化法
  6. 自组织的网游金融体系
  7. HEVCProfileMain10HDR10 和 非8bit数据位深的一些讨论。
  8. java8List根据某个属性排序
  9. 常见期权策略一览(期权,组合)
  10. 100个python算法超详细讲解:画直线