在将分区过滤器应用于Spark(v2.0.2 / 2.1.1)DataFrame时遇到问题,这些DataFrame从具有超过30,000个分区的Hive(v2.1.0)表中读取。我想知道推荐的方法是什么,以及我做错了什么,因为当前的行为是大性能的可靠性问题的来源。
要启用修剪,我使用以下Spark / Hive属性:
--conf spark.sql.hive.metastorePartitionPruning=true
在spark-shell中运行查询时,我可以看到分区提取发生时调用ThriftHiveMetastore.Iface.get_partitions
,但是这意外地发生了没有任何过滤:
val myTable = spark.table("db.table")
val myTableData = myTable
.filter("local_date = '2017-09-01' or local_date = '2017-09-02'")
.cache
// The HMS call invoked is:
// #get_partitions('db', 'table', -1)
如果我使用更简单的过滤器,则会根据需要过滤分区:
val myTableData = myTable
.filter("local_date = '2017-09-01'")
.cache
// The HMS call invoked is:
// #get_partitions_by_filter(
// 'db', 'table',
// 'local_date = "2017-09-01"',
// -1
// )
如果我重写过滤器以使用范围运算符而不是简单地检查相等性,过滤也可以正常工作:
val myTableData = myTable
.filter("local_date >= '2017-09-01' and local_date <= '2017-09-02'")
.cache
// The HMS call invoked is:
// #get_partitions_by_filter(
// 'db', 'table',
// 'local_date >= '2017-09-01' and local_date <= '2017-09-02'',
// -1
// )
在我们的案例中,从性能角度来看,这种行为是有问题的;如果正确过滤,通话时间在4分钟到1秒之间。此外,每次查询常规地将大量Partition
个对象加载到堆上最终会导致Metastore服务中出现内存问题。
似乎在某些类型的过滤器结构的解析和解释方面存在一个错误,但是我无法在Spark JIRA中找到相关问题。是否有首选方法或特定Spark版本,其中筛选器正确应用于所有筛选器变体?或者我必须在构建过滤器时使用特定形式(例如范围运算符)?如果是这样,这个限制是否记录在任何地方?
答案 0 :(得分:0)
我没有找到一种首选的查询方式,除了重写过滤器,如我的(OP)问题所述。我确实发现spark已经改进了对此的支持,看起来我的案例在Spark 2.3.0中得到了解决。这是解决我发现的问题的票证:SPARK-20331