Spark3动态分区裁剪(Dynamic Partition Pruning,DPP)
参数:spark.sql.optimizer.dynamicPartitionPruning.enabled
默认开启
执行条件:
①、需要剪裁的表必须是分区表且分区字段必须在on条件中
②、join类型必须是 inner、left(右表是分区表)、right(左表是分区表)、left semi(右表是分区表)
③、spark.sql.optimizer.dynamicPartitionPruning.useStats:是否使用统计信息进行动态分区裁剪有益判断;这里的信息指的是属性的CBO统计信息,计算所有可能的物理计划的代价并挑选代价最小的物理执行计划。
spark.sql.optimizer.dynamicPartitionPruning.fallbackFilterRatio:在动态分区裁剪之后的计算分区大小的过滤比率,评估是否进行动态分区裁剪
两个参数综合评估出一个进行动态分区裁减是否有益的值,满足了才会进行动态分区裁减。
小表:spark.range(1, 100).select($“id”, " i d " ∗ 10 a s ( " n a m e 1 " ) ) . w r i t e . p a r t i t i o n B y ( " i d " ) . p a r q u e t ( " / t 1 " ) 大 表 : s p a r k . r a n g e ( 1 , 10000 ) . s e l e c t ( "id" * 10 as ("name1")).write.partitionBy("id").parquet("/t1") 大表:spark.range(1, 10000).select( "id"∗10as("name1")).write.partitionBy("id").parquet("/t1")大表:spark.range(1,10000).select(“id”, $“id” as (“name2”)).write.partitionBy(“id”).parquet("/t2")
读取:val df1 = spark.read.parquet(“hdfs/t1”)
val df2 = spark.read.parquet(“hdfs/t2”)
注册视图:df1.createTempView(“v1”)
df2.createTempView(“v2”)
过滤条件与on字段不是同一字段
val df3 = spark.sql(“select tab1.id, tab1.name1, tab2.id, tab2.name2 from tab1 join tab2 on tab1.id = tab2.id and tab1.name1 <= 150”)
在这种情况下动态分区裁剪很有必要,tab2会提前知道自己应该scan那些数据
df3.show 耗时 1s
执行计划:
大表在scan之前拿到小表broadcast exchange的结果从而达到避免扫描无用的数据的效果。
过滤条件与on字段是同一字段
val df3 = spark.sql(“select tab1.id, tab1.name1, tab2.id, tab2.name2 from tab1 join tab2 on tab1.id = tab2.id and tab1.id<= 5”)
join tab2 on tab1.id = tab2.id and tab1.id<= 5 => 1.id = 2.id and 1.id <= 5 and 2.id <= 5
动态分区裁剪在这一过程中将会是无效的
df3.show 耗时 0.4s
执行计划:
会将过滤条件直接下推到两个表,减少无用数据的过滤
动态分区裁剪关闭:
过滤条件与on字段不是同一字段
val df3 = spark.sql(“select tab1.id, tab1.name1, tab2.id, tab2.name2 from tab1 join tab2 on tab1.id = tab2.id and tab1.name1 <= 150”)
df3.show 耗时 41s
执行计划:
会将tab2中的数据全部输出
过滤条件与on字段是同一字段
val df3 = spark.sql(“select tab1.id, tab1.name1, tab2.id, tab2.name2 from tab1 join tab2 on tab1.id = tab2.id and tab1.id <= 150”)
join tab2 on tab1.id = tab2.id and tab1.id<= 5 => 1.id = 2.id and 1.id <= 5 and 2.id <= 5
动态分区裁剪在这一过程中将会是无效的
df3.show 耗时 1s
执行计划:
过滤条件下推到tab2,也能够直接输出有价值的数据