Parquet 整体说明
- Parquet(Apache Parquet)是一种列式存储的二进制文件格式,专为大数据处理场景设计,具有高效压缩和编码特性
- Parquet 尤其适合分析型工作负载,能显著提升查询速度并降低存储成本
Parquet 文件结构
- Parquet文件由多个行组(Row Groups)组成,每个行组包含:
- 列块(Column Chunks) :存储实际列数据
- 元数据 :记录统计信息(如min/max),用于加速查询
parquet-tools 工具快速查看 parquet 文件
- 工具安装包下载页面:https://github.com/hangxie/parquet-tools/releases
- 下载后安装
- 安装后即可 通过
parquet-tools快速访问 parquet 文件 - 注:M 系列 Mac 安装时直接下载 parquet-tools-v1.53.1-darwin-arm64.gz 版本解压后放到指定目录下就可以用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# 下载文件
wget https://github.com/hangxie/parquet-tools/releases/download/v1.53.1/parquet-tools-v1.53.1-darwin-arm64.gz
# 解压文件
gzip -d -c parquet-tools-v1.53.1-darwin-arm64.gz > parquet-tools-v1.53.1-darwin-arm64
# Liunx 中也可以用 gunzip parquet-tools-v1.53.1-darwin-arm64.gz
# 移动到指定目录
sudo mv parquet-tools-v1.53.1-darwin-arm64 /usr/local/bin/parquet-tools
# 添加执行权限
chmod +x /usr/local/bin/parquet-tools
# Mac 安全检查可能需要下面的命令(用管理员权限,彻底清空该文件所有扩展隐藏属性)
sudo xattr -cr /usr/local/bin/parquet-tools
统计行数
- 行数查看:
1
parquet-tools row-count file.parquet
查看结构
结构查看
1
parquet-tools schema file.parquet
常结合 jq 打印 json 可读版本
1
parquet-tools schema file.parquet | jq
查看某些行
常常结合 json 格式来访问和查看:
1
2
3# 抽取第一行并用 json 格式打印
# 注:有的版本使用的是 parquet-tools head -n 来访问,具体需要看安装的版本,如 Go,Python,Java 等版本
parquet-tools cat -l 2 test.parquet | jq '.'parquet-tools cat -l抽取到的一般是一个 list ,所以常用下面的方式查看具体的一个完整 json 对象:1
2# 抽取第一行并用 json 格式打印
parquet-tools cat -l 1 test.parquet | jq '.[0]'查看中间某些行(下面是第 11 到 15 行):
1
parquet-tools cat --offset 10 -l 5 file.parquet
拆分文件
拆分文件(不好用)
1
2
3
4# 将文件按照最多 xxx 行一个文件拆分,命名形式为 part-000001.parquet 形式,若不指定
parquet-tools split --record-count 1000 --name-format "part-%06d.parquet" test.parquet
# parquet-tools 不支持仅输出 前 xxx 行,需要手动删除其余文件--name-format制定格式,不指定本参数时,默认格式是 “result-%06d.parquet” 形式
建议使用下面的 Python 来读写前 N 行
1
2
3import polars as pl
df = pl.read_parquet('test.parquet')
df.head(1000).write_parquet('sample.parquet')- 也可以将这个 python 代码写成可复用的脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53#!/usr/bin/env python3
"""
Extract the first N rows from a Parquet file and save as a new Parquet file.
Usage:
python extract_rows.py -i input.parquet -o output.parquet -n 1000
"""
import argparse
import polars as pl
from pathlib import Path
def main():
parser = argparse.ArgumentParser(
description="Extract the first N rows from a Parquet file."
)
parser.add_argument(
"-i", "--input",
required=True,
help="Path to the input Parquet file."
)
parser.add_argument(
"-o", "--output",
required=True,
help="Path to the output Parquet file. "
)
parser.add_argument(
"-n", "--lines",
type=int,
required=True,
help="Number of rows to extract from the beginning. "
)
args = parser.parse_args()
input_path = Path(args.input)
if not input_path.exists():
print(f"Error: Input file '{input_path}' does not exist.")
return 1
try:
df = pl.read_parquet(input_path)
df.head(args.lines).write_parquet(args.output)
print(f"Successfully extracted {args.lines} rows to '{args.output}'.")
except Exception as e:
print(f"Error: {e}")
return 1
return 0
if __name__ == "__main__":
exit(main())
- 也可以将这个 python 代码写成可复用的脚本
合并文件
- 合并文件
1
2
3
4
5# 方式 A:逗号分隔
parquet-tools merge merge.parquet -s test.parquet,train.parquet
# 方式 B:多次 -s
parquet-tools merge merge.parquet -s test.parquet -s train.parquet
Parquet 文件读取示例
- Spark :
df.write.parquet("path")/spark.read.parquet("path") - Pandas :
pd.read_parquet("file.parquet", engine="pyarrow") - Hive :
CREATE TABLE ... STORED AS PARQUET
附录:文件读取和分析示例
- 使用 Python 代码读取并解析文件格式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34import pandas as pd
def read_and_inspect_parquet(file_path):
try:
# 读取Parquet文件
df = pd.read_parquet(file_path)
print("成功读取Parquet文件!")
print("\n===== 数据基本信息 =====")
df.info() # 显示数据框的基本信息,包括列名、数据类型、非空值数量等
for col in df.columns:
print("col:", col)
print(df[col][0])
print("\n===== 前5行数据 =====")
print(df.head()) # 显示前5行数据,查看数据格式
print("\n===== 数据统计信息 =====")
print(df.describe()) # 显示数值型列的统计信息
return df
except FileNotFoundError:
print(f"错误: 找不到文件 '{file_path}'")
except Exception as e:
print(f"读取Parquet文件时发生错误: {str(e)}")
return None
if __name__ == "__main__":
parquet_file_path = "./gsm8k/test.parquet"
# 读取并查看Parquet文件
dataframe = read_and_inspect_parquet(parquet_file_path)
附录:列式存储 vs 行式存储
- 行式存储(如CSV、JSON):按行存储数据,适合整行读取的场景(如单条记录查询)
- 列式存储(如Parquet):按列存储数据,适合只读取部分列或聚合分析的场景(如计算某列的平均值)