我正在尝试将spark中的hive表作为强类型Dataset
读取,并且我注意到分区没有被修剪而不是在同一hive表的数据帧上执行Spark SQL。
case class States(state: String, country: String)
val hiveDS = spark.table("db1.states").as[States]
//no partition pruning
hiveDS.groupByKey(x=>x.country).count().filter(x=>x._1 == "US")
状态按国家/地区划分,因此当我对上述数据集进行计数时,查询将扫描所有分区。但是,如果我这样读它 -
val hiveDF = spark.table("db1.states")
//correct partition pruning
hiveDF.groupByKey("country").count().filter(x=>x._1 == "US")
正确修剪分区。有人可以解释为什么在将表映射到案例类时会丢失分区信息吗?
答案 0 :(得分:3)
TL; DR 第一种情况下缺少分区修剪是预期的行为。
之所以发生这种情况,是因为对于对象的任何操作,与DataFrame
DSL / SQL使用的操作不同,是一个黑盒子,从优化器的角度来看。为了能够优化像x=> x._1 == "US"
或x => x.country
这样的函数,Spark必须应用复杂且不可靠的静态分析,并且这样的功能既不存在也不会(据我所知)计划在未来。< / p>
第二种情况不应该编译(没有groupByKey
变体需要字符串),所以不可能告诉,但一般来说它也不应该修剪,除非你的意思:
hiveDF.groupBy($"country").count().filter($"country" =!= "US")
另见我对Spark 2.0 Dataset vs DataFrame的回答。