问题说明
使用Spark SQL 访问Hive 表的一个表分区,但是运行速度却很慢。
分析样例:
select** x,y from test where **x=1 (其中x是test表的 Partition 字段)
原因分析
按照spark 源码逻辑,在解析逻辑计划时候回去调用 getPartitionsByFilter方法 去hive中只提取 x=1 分区信息。
但是由于一些原因,导致getPartitionsByFilter 的谓词下推失败,从而去全表扫描所有test的分区信息,并返回。
例如,我们x字段是String类型,但是我们的SQL中不是 where x=’1’ ,而是where x=1 ,这就导致了谓词下推失败。
出现hive分区表谓词下推失败的情况,我们可以做如下处理:
- 我们需要去检查sql中的写法是否正确。
- 可以关闭SQL逻辑计划解析过程中的谓词下推逻辑。
处理步骤
关闭SQL逻辑计划解析过程中的谓词下推逻辑,具体是Spark SQL默认开启基于分区统计信息的执行计划优化,相当于自动执行Analyze Table(默认开启的设置方法为spark.sql.statistics.fallBackToHdfs=true,可通过配置为false关闭)。
开启后,SQL执行过程中会扫描表的分区统计信息,并作为执行计划中的代价估算,例如对于代价评估中识别的小表,会广播小表放在内存中广播到各个节点上,进行join操作,大大节省shuffle时间。
此开关对于Join场景有较大的性能优化,但是会带来 获取分区表信息RPC请求 的增加。
在SparkSQL中设置以下参数后再运行:
set spark.sql.statistics.fallBackToHdfs=false;
或者在启动之前使用--conf设置这个值为false:
--conf spark.sql.statistics.fallBackToHdfs=false