选择正确的文件格式对于构建高性能数据应用程序很重要。本文中概述的概念适用于 Pandas、Dask、Spark 和 Presto / AWS Athena。
列修剪
列修剪是一项重大的性能改进,它可以用于基于列的文件格式(Parquet、ORC),但不能用于基于行的文件格式(CSV、Avro)。
假设您有一个包含 100 列的数据集,并且想要将其中的两列读入 DataFrame。如果数据存储在 Parquet 文件中,您可以使用 Pandas 执行此操作。
import pandas as pd
pd.read_parquet('some_file.parquet', columns = ['id', 'firstname'])
Parquet 是一种列文件格式,因此 Pandas 可以抓取与查询相关的列,并且可以跳过其他列。这是一个巨大的性能改进。
如果数据存储在 CSV 文件中,您可以这样读取:
import pandas as pd
pd.read_csv('some_file.csv', usecols = ['id', 'firstname'])
usecols 不能跳过整个列,因为 CSV 文件格式的行性质。
Spark 不要求用户明确列出将在查询中使用的列。 Spark 建立了一个执行计划,并尽可能地自动利用列修剪。当然,只有在底层文件格式是面向列的情况下,才能进行列修剪。
人气
Spark 和 Pandas 内置了 CSV、JSON、ORC、Parquet 和文本文件的读写器。他们没有内置的 Avro 阅读器。
Avro 在 Hadoop 生态系统中很受欢迎。 Parquet 在 Hadoop 生态系统之外获得了巨大的关注。例如,Delta Lake 项目是基于 Parquet 文件构建的。
Arrow 是一个重要的项目,它使使用各种不同的语言(C、C++、Go、Java、JavaScript、MATLAB、Python、R、Ruby、Rust)轻松处理 Parquet 文件,但没有t 支持 Avro。 Parquet 文件更易于使用,因为它们受到许多不同项目的支持。
架构
Parquet 将文件架构存储在文件元数据中。 CSV 文件不存储文件元数据,因此需要向读者提供架构或推断架构。提供模式很乏味,推断模式容易出错/代价高昂。
Avro 还将数据模式存储在文件本身中。在文件中包含架构是一个巨大的优势,这也是现代数据项目不应依赖 JSON 或 CSV 的原因之一。
列元数据
Parquet 商店 metadata statistics for each column 和 lets users add their own column metadata 也是如此。
最小/最大列值元数据允许 Dask 和 Spark 集群计算框架支持的 Parquet 谓词下推过滤。
以下是使用 PyArrow 获取列统计信息的方法。
import pyarrow.parquet as pq
parquet_file = pq.ParquetFile('some_file.parquet')
print(parquet_file.metadata.row_group(0).column(1).statistics)
<pyarrow._parquet.Statistics object at 0x11ac17eb0>
has_min_max: True
min: 1
max: 9
null_count: 0
distinct_count: 0
num_values: 3
physical_type: INT64
logical_type: None
converted_type (legacy): NONE
复杂的列类型
Parquet 允许使用复杂的列类型,例如数组、字典和嵌套模式。没有可靠的方法以简单的文件格式(如 CSV)存储复杂类型。
压缩
列文件格式将相关类型存储在行中,因此更易于压缩。这个 CSV 文件比较难压缩。
first_name,age
ken,30
felicia,36
mia,2
当相关类型存储在同一行时,这些数据更容易压缩:
ken,felicia,mia
30,36,2
Parquet 文件最常使用 Snappy 压缩算法进行压缩。 Snappy 压缩文件是可拆分的并且可以快速膨胀。大数据系统希望减少磁盘上的文件大小,但也希望快速膨胀并运行分析查询。
文件的可变性
Parquet 文件是不可变的,as described here。 CSV 文件是可变的。
向 CSV 文件添加一行很容易。您无法轻松地将行添加到 Parquet 文件。
数据湖
在大数据环境中,您将处理成百上千个 Parquet 文件。文件的磁盘分区、避免大文件和压缩小文件很重要。数据的最佳磁盘布局取决于您的查询模式。