Spark分区表先过滤首分区列再过滤次列count distinct变慢原因
问题原因分析
核心根因
性能差异来自Spark缓存的误命中,从你提供的执行计划可以直接定位问题:
- 慢查询的执行计划里明确出现
InMemoryRelation和StorageLevel标识,说明你之前对仅过滤A列的DataFrame执行过cache()/persist()操作,且这份缓存保留了全量字段,没有做列裁剪。 - 当你按照
先过滤A、再过滤B的顺序写条件时,Spark优化器会判定当前查询可以复用之前的A过滤缓存结果,不会再把A、B两个过滤条件下推到源Parquet做分区裁剪,而是直接读取全量缓存数据后再做B列过滤、D列提取和后续聚合。缓存里的全量字段数据量远大于直接扫源文件分区裁剪后的结果,自然会慢几个数量级。 - 当你调换过滤顺序为
先过滤B、再过滤A时,查询逻辑和已有的仅A过滤的缓存匹配不上,Spark就会放弃走缓存,直接将两个分区过滤条件都下推到源Parquet扫描,正常触发分区裁剪和列裁剪,只读取符合条件的分区里的D列数据,所以速度恢复正常。
解决方法
- 先清理不必要的缓存:对不需要保留的中间缓存调用
unpersist()释放即可,也可以执行spark.catalog.clearCache()清空当前会话的所有缓存验证问题。 - 如果确实需要缓存A过滤后的结果,缓存前先做列裁剪,只保留后续需要用到的列,减少缓存占用的内存和扫描开销。
内容的提问来源于stack exchange,提问作者DeanLa
相关产品推荐
相关产品推荐

