如何验证Polars在过滤时是否利用文件统计信息,并查看查询实际打开的Parquet文件
这个问题问到了点子上——Parquet的文件级统计剪枝是提升大数据查询性能的关键手段之一,我来帮你一步步验证Polars的行为,搞清楚它到底有没有做剪枝,以及实际打开了哪些文件:
第一步:先确认你的Parquet文件本身包含有效的ts_index统计信息
Polars要做文件剪枝的前提是:每个Parquet文件的元数据里必须包含ts_index列的min/max统计值。如果这些统计不存在,Polars根本没办法判断哪些文件需要过滤。
你可以用Polars自带的read_parquet_metadata函数批量检查所有文件的统计信息,代码示例如下(已经适配GCS路径,前提是你已经配置好GCS的访问权限):
import polars as pl # 生成所有71个文件的路径 parquet_files = [f"gs://path/to/table/partitions.parquet/p{i}.parquet" for i in range(71)] for file_path in parquet_files: # 读取单个文件的元数据 metadata = pl.read_parquet_metadata(file_path) # 遍历schema找到ts_index的统计信息 for elem in metadata.schema: if elem.name == "ts_index": stats = elem.statistics if stats: print(f"📄 文件: {file_path.split('/')[-1]}") print(f" ts_index 最小值: {stats.min}, 最大值: {stats.max}") print("---") else: print(f"⚠️ 文件 {file_path.split('/')[-1]} 没有ts_index的统计信息!")
如果输出里有文件显示没有统计信息,那你需要重新生成这些Parquet文件时开启统计(比如用Polars写文件时指定write_statistics=True,这是默认值,但之前的生成过程可能被关闭了)。
第二步:查看Polars优化后的查询计划,确认文件剪枝是否生效
你之前用的df.explain()输出的是未优化的逻辑计划,它会列出所有候选文件,但Polars在实际执行前会做优化。你需要用explain(optimized=True)查看优化后的物理计划,这里会显示Polars实际要扫描的文件:
parquet_path = 'gs://path/to/table/partitions.parquet/' df = pl.scan_parquet(parquet_path).filter((pl.col("ts_index") >= 1000) & (pl.col("ts_index") < 10000)) # 查看优化后的执行计划 print(df.explain(optimized=True))
如果Polars成功利用了统计信息做剪枝,输出里的Parquet SCAN部分只会列出1-2个符合条件的文件,而不是全部71个。
第三步:直接监控实际打开的文件(最靠谱的验证方式)
计划归计划,实际执行的行为才是最准确的,你可以通过两种方式监控:
方式1:开启Polars的DEBUG日志,打印文件访问细节
Polars的DEBUG日志会详细输出查询执行过程中的文件操作,包括实际打开的Parquet文件。代码示例:
import polars as pl import logging # 配置日志级别为DEBUG,让Polars输出详细执行日志 logging.basicConfig( level=logging.DEBUG, format="%(levelname)s: %(message)s" ) # 运行你的查询并触发执行 parquet_path = 'gs://path/to/table/partitions.parquet/' lazy_df = pl.scan_parquet(parquet_path, use_statistics=True).filter( (pl.col("ts_index") >= 1000) & (pl.col("ts_index") < 10000) ) # collect()触发实际执行 result_df = lazy_df.collect()
运行这段代码后,你会在控制台看到类似这样的日志:
DEBUG: Opening parquet file 'gs://path/to/table/partitions.parquet/p15.parquet' DEBUG: Reading column 'ts_index' from file 'gs://path/to/table/partitions.parquet/p15.parquet'
通过这些日志,你可以清晰看到Polars实际打开了哪些文件,完全不用猜。
方式2:查看云存储的访问日志(针对GCS)
如果你用的是GCS,可以开启存储桶的访问日志,之后通过Cloud Logging查看哪些Parquet文件被Polars读取了。这种方式适合生产环境的监控,能准确统计所有的文件访问行为。
第四步:检查Polars的关键配置
最后,确认几个Polars的参数是否正确设置:
use_statistics=True:这个参数是scan_parquet的默认值,但你可以显式设置它,确保Polars会尝试使用Parquet统计信息。- 远程存储的文件系统配置:对于GCS,确保你使用的文件系统(比如
gcsfs)能高效获取文件元数据,Polars需要读取所有文件的元数据来做剪枝,元数据获取的效率会影响剪枝的触发。
额外提醒
就算Polars打开了某个文件,也不代表它会读取文件的所有内容——它还会利用行组级别的统计信息跳过不需要的行组。比如如果一个文件里只有部分行组的ts_index在你的过滤范围内,Polars只会读取那些符合条件的行组。
备注:内容来源于stack exchange,提问作者LRMB33

