如何防止谓词下推?
Posted
技术标签:
【中文标题】如何防止谓词下推?【英文标题】:How to prevent predicate pushdown? 【发布时间】:2018-05-14 17:57:11 【问题描述】:最近我正在使用带有 JDBC 数据源的 Spark。考虑以下 sn-p:
val df = spark.read.(options).format("jdbc").load();
val newDF = df.where(PRED)
PRED 是谓词列表。
如果 PRED 是一个简单的谓词,例如 x = 10
,查询会快得多。但是,如果有一些非等值条件,如date > someOtherDate or date < someOtherDate2
,查询比没有谓词下推要慢得多。您可能知道,数据库引擎对此类谓词的扫描非常慢,在我的情况下甚至慢了 10 倍(!)。
为了防止不必要的谓词下推,我使用了:
val cachedDF = df.cache()
val newDF = cachedDF.where(PRED)
但它需要大量内存并且 - 由于这里提到的问题 - Spark' Dataset unpersist behaviour - 我无法取消持久性 cachedDF
。
还有其他选择可以避免下推谓词吗?没有缓存也没有编写自己的数据源?
注意:即使有关闭谓词下推的选项,它也只适用于其他查询可能仍然使用它。所以,如果我写:
// some fancy option set to not push down predicates
val df1 = ...
// predicate pushdown works again
val df2 = ...
df1.join(df2)// where df1 without predicate pushdown, but df2 with
【问题讨论】:
虽然我不知道(这并不意味着它当然不会退出)任何可以禁用谓词下推的方法(除了破解计划 /simple/ 或添加自定义规则来放置分析障碍/没有尝试过,应该可以/)我强烈反对数据库引擎对此类谓词的扫描非常慢。这让我产生了疑问——你确定谓词被推倒了吗(Spark 对此不是很聪明)。 @user6910411 是的,我在explain()
结果和发送到数据库的 SQL 中看到了它。据我所知,数据库引擎通常在非常复杂的谓词上性能很差,其中有许多非相等条件,它们之间有 OR。就我而言,没有下推式 WHERE 子句的 SQL 大约是。快 10 倍
OR
谓词与范围搜索不同,但我上次检查时,OR
s 没有被下推,不包括同一字段上的链式相等条件的情况 (@987654331 @)
话虽如此 - 简单的破解方法是传递字段udf[T, T](identity _)
。强制转换可以以类似的方式工作。例如 `df.where(($"modifieddate" > "2010-05-28 00:00:00"))` 其中modifieddate
是时间戳,而df.where(($"modifieddate" > lit("2010-05-28 00:00:00").cast("timestamp")))
将是
我认为你错过了我的观点。缓存的问题是可以完全禁用下推。但是,如果您将一些谓词推送到查询字符串中,Spark 将不会触及这部分。但这当然是另一个 hack。
【参考方案1】:
已为此问题打开 JIRA 票证。你可以在这里关注它: https://issues.apache.org/jira/browse/SPARK-24288
【讨论】:
以上是关于如何防止谓词下推?的主要内容,如果未能解决你的问题,请参考以下文章