在 DuckDB 中读取分区的 parquet 文件

问题描述 投票:0回答:3

背景

  • DuckDB 允许直接查询 parquet 文件。例如con.execute("从'Hierarchy.parquet'中选择*)

  • Parquet 允许按列值对文件进行分区。对 parquet 文件进行分区时,将使用 parquet 文件的名称和列值的子文件夹创建顶级文件夹,然后这些子文件夹包含实际的 parquet 数据文件。例如 Hierarchy.parquet(文件夹)--> date=20220401(子文件夹)-->part1.parquet

预期行为

DuckDB 用于查询分区和未分区的 parquet 文件。

观察到的行为

DuckDB 在查询分区的 parquet 文件时失败,但可以处理未分区的 parquet 文件。

con.execute("Select * from 'Hierarchy.parquet'")
失败
RuntimeError: IO Error: No files found that match the pattern "Hierarchy.parquet"
当 Hierarchy.parquet 分区时。

查询底层个人数据文件工作正常:

con.execute("Select * from 'Hierarchy.parquet/date=20220401/part1.parquet'")

有没有办法用 DuckDB 查询分区的 parquet 文件?或者这是一个限制/错误?

parquet duckdb
3个回答
6
投票

这在

中作为 DuckDB 问题/功能请求进行讨论

“支持镶木地板档案的蜂巢式分区” https://github.com/duckdb/duckdb/issues/2186

建议的解决方法是:

  • 使用分区参数将 parquet 文件打开为 arrow/pyarrow 数据集
  • 将数据集注册为 DuckDB 中的视图
  • 查询视图
import pyarrow.dataset as ds
import duckdb

con = duckdb.connect()

dataset = ds.dataset("Hierarchy.parquet", format="parquet", partitioning="hive")
con.register_arrow("Hierarchy", dataset)
con.execute("Select * from Hierarchy").df()

DuckDB 的直接支持会更好...但这工作正常并且很简单。


2
投票

至少需要 DuckDB 0.4.1 才能支持分区 parquet 文件。

pip install -U --pre duckdb

例如,如果您的镶木地板按物种划分,

['/Users/steven/data/iris1/Species=setosa/0-06ea69fc-393b-4dc7-8940-46700d407ec4-0.parquet',
 '/Users/steven/data/iris1/Species=virginica/0-06ea69fc-393b-4dc7-8940-46700d407ec4-0.parquet',
 '/Users/steven/data/iris1/Species=versicolor/0-06ea69fc-393b-4dc7-8940-46700d407ec4-0.parquet']

您可以这样查询,

select * from parquet_scan(['/Users/steven/data/iris1/Species=setosa/0-06ea69fc-393b-4dc7-8940-46700d407ec4-0.parquet',
 '/Users/steven/data/iris1/Species=virginica/0-06ea69fc-393b-4dc7-8940-46700d407ec4-0.parquet',
 '/Users/steven/data/iris1/Species=versicolor/0-06ea69fc-393b-4dc7-8940-46700d407ec4-0.parquet']
                           , HIVE_PARTITIONING=true);

你会得到, enter image description here

参数

HIVE_PARTITIONING=true
非常重要。


0
投票

我们的目标是双重的:

  1. 利用 Parquet 过滤器加载部分数据集 对应分区键。
  2. 使用 DuckDB 编写查询 过滤后的数据集。

我创建了一个按州分区的城市数据的玩具 Parquet 数据集。源 csv 文件如下所示(总共 25 行):

rank,city,state,population,2000_2013_growth
1,New York,New York,8405837,4.8%
2,Los Angeles,California,3884307,4.8%
3,Chicago,Illinois,2718782,-6.1%

导入我需要的包:

import duckdb
import pandas as pd
import pyarrow.parquet as pq

我的第一个目标是将分区数据的子集转换为 DuckDB 可以查询的内容,在本例中是 Pandas 数据框:

parquet_file = f'{parquet_folder}/city_data.parquet'
filter_column = 'State'
states = ['California', 'Michigan', 'New York']
ds = pq.ParquetDataset(parquet_file, filters=[('state','in', states)])
df = ds.read().to_pandas()

接下来我将构建一个查询,一个简单的例子是:

query = """SELECT * FROM df WHERE State = 'California'"""
results_df = duckdb.query(query).to_df()

我刚刚开始使用 Parquet 和 DuckDB,所以我声称没有专业知识,这可能不是最好的方法。很高兴看到其他人添加他们的改进建议。

© www.soinside.com 2019 - 2024. All rights reserved.