假设我的数据存储在对象存储中,比如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文档,我可以使用filters
arg来检索如下数据的子集:
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(。