如何防止谓词下推?

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 谓词与范围搜索不同,但我上次检查时,ORs 没有被下推,不包括同一字段上的链式相等条件的情况 (@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

【讨论】:

以上是关于如何防止谓词下推?的主要内容,如果未能解决你的问题,请参考以下文章

谓词下推

创建没有下推谓词的动态框架问题

聊聊谓词下推的事

使用 Dask 进行 Parquet 谓词下推过滤

使用 PyArrow + Parquet + Google Cloud Storage 时如何实现谓词下推?

什么是谓词下推,看这一篇就够了