如何使用熊猫的read_parquet有效地读取过滤的分区镶木地板文件?



假设我的数据存储在对象存储中,比如s3,日期-时间分区如下:

s3://my-bucket/year=2021/month=01/day=03/SOME-HASH-VAL1.parquet
...
s3://my-bucket/year=2022/month=12/day=31/SOME-HASH-VAL1000.parquet

根据pandas的read_parquet-api文档,我可以使用filtersarg来检索如下数据的子集:

pd.read_parquet(
"s3://my-bucket/",
filters=[("year", ">=",  2021)],
)

但当我想在特定日期之后检索数据时,就会出现问题,比如2021-08-31:

pd.read_parquet(
"s3://my-bucket/",
filters=[("year", ">=",  2021), ("month", ">", 8)],
)

这里看起来没有什么问题,但它过滤掉了2022-01到2022-07的数据范围。

可能的解决方案是用这样的分区存储数据:

s3://my-bucket/dt=2021-01-03/SOME-HASH-VAL.parquet
...
s3://my-bucket/dt=2022-12-31/SOME-HASH-VAL.parquet

但随着时间的推移,比如10年后,这可能会成为一个问题,因为bucket将有365x10=3650个文件夹,这可能导致读取数据时的性能问题。

我该如何明智地解决这些问题?

您实际上可以使用数据结构正确地过滤数据:

filters=[
[("year", ">", 2021)],
[("year", "=", 2021), ("month", ">", 8)],
[("year", "=", 2021), ("month", "=", 8), ("day", ">=", 31)]
]

根据文件:

谓词以析取范式(DNF(表示,如[[('x','=',0(,…],…]。DNF允许单列谓词的任意布尔逻辑组合。最里面的元组分别描述一个单列谓词。内部谓词列表被解释为连接(AND(,形成一个更具选择性的多列谓词。最后,最外层的列表将这些过滤器组合为析取(OR(。

相关内容

  • 没有找到相关文章

最新更新