组合 Spark UDF(而不是将 UDF 作为一个)时是否会造成性能损失?

2024-04-07

我想知道编写 Spark udf 是否会降低性能。一般来说,我更喜欢编写只做一件事的小函数……

这是一个简单的例子,给定一个DataFrame df :

def inc = udf( (i: Double) => i + 1)
def double = udf( (i: Double) => i * 2)
df.withColumn("r", double(inc($"c")))

versus

def incAndDouble = udf( (i: Double) => (i + 1) * 2)
df.withColumn("r", incAndDouble($"c")

据我所知,这个简单示例的性能是相同的。

你能解释一下为什么吗? Spark 在幕后如何工作?

总是如此吗?

[update]

当可以进行巧妙的组合(不仅仅是简单的函数组合)时,我可能有一个反例,如下例所示

def filter = udf((s: Seq[String]) => s.startsWith("A"))
def size = udf((s: Seq[String]) => s.size)

val filterAndSize = udf((s: Seq[String]) => s.count(_.startsWith("A")))

因此,我认为 filterAndSize 更可取,因为它将避免一些中间集合实例化。


TL;DR可能会出现一些性能下降或损失,但可以忽略不计。

你能解释一下为什么吗?

看到你的问题带有“explain”,这很有趣,这正是用来查看 Spark SQL 背后发生的情况以及它如何执行查询的方法的名称:)

So, use Dataset.explain甚至更详细的版本Dataset.explain(extended = true)查看所有优化(以及可能的性能下降)。

def inc = udf( (i: Double) => i + 1)
def double = udf( (i: Double) => i * 2)

val df = Seq(1,2,3).toDF("c")
val q = df.withColumn("r", double(inc($"c")))

由两个 UDF 组成的计划如下所示。

scala> q.explain(extended = true)
== Parsed Logical Plan ==
'Project [c#3, UDF(UDF('c)) AS r#10]
+- AnalysisBarrier Project [value#1 AS c#3]

== Analyzed Logical Plan ==
c: int, r: double
Project [c#3, if (isnull(if (isnull(cast(c#3 as double))) null else UDF(cast(c#3 as double)))) null else UDF(if (isnull(cast(c#3 as double))) null else UDF(cast(c#3 as double))) AS r#10]
+- Project [value#1 AS c#3]
   +- LocalRelation [value#1]

== Optimized Logical Plan ==
LocalRelation [c#3, r#10]

== Physical Plan ==
LocalTableScan [c#3, r#10]

让我们看看一个 UDF(两个 UDF 的组合)的计划是什么样子的。

def incAndDouble = udf( (i: Double) => (i + 1) * 2)
val q = df.withColumn("r", incAndDouble($"c"))
scala> q.explain(extended = true)
== Parsed Logical Plan ==
'Project [c#3, UDF('c) AS r#16]
+- AnalysisBarrier Project [value#1 AS c#3]

== Analyzed Logical Plan ==
c: int, r: double
Project [c#3, if (isnull(cast(c#3 as double))) null else UDF(cast(c#3 as double)) AS r#16]
+- Project [value#1 AS c#3]
   +- LocalRelation [value#1]

== Optimized Logical Plan ==
LocalRelation [c#3, r#16]

== Physical Plan ==
LocalTableScan [c#3, r#16]

在这种特殊情况下,差异是没有的,因为跨查询的物理计划是相同的,即LocalTableScan.

它可能与文件或 JDBC 等其他数据源不同,但我个人的建议是开发尽可能小的 UDF,因为它们是 Spark 优化器的黑匣子。


总是如此吗?

不,一点也不,因为这在很大程度上取决于您在 UDF 中所做的事情(但这更多地与是否首先编写 UDF 有关)。

在以下 UDF 为谓词的情况下(即返回布尔值):

def filter = udf((s: Seq[String]) => s.startsWith("A"))

Spark 可以优化 UDF 的使用(如果是的话)not一个 UDF 但很简单filter操作)并将其下推到数据源以加载更少的数据。这可能会对性能产生巨大影响。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

组合 Spark UDF(而不是将 UDF 作为一个)时是否会造成性能损失? 的相关文章

随机推荐

  • 如何使用 ACM 库 (ConsoleProgram) 编写 Java 程序?

    我想问一个关于我的程序的小问题 这是我的代码示例 public static void main String args int q int p int thelargest int thesmallest Scanner input ne
  • Angular 2 路由器路径

    我有两个关于 Angular 2 路由器路径的问题 我花了一些时间在谷歌上搜索它 但没有运气 无论如何我有以下路由设置 path contract component ContractInsertUpdateComponent childr
  • 远程片段上的引导模式“加载”事件

    我目前正在使用 Twitter Bootstrap 模式组件 并且遇到一个问题 我在使用 data remote 属性远程加载的内容中的输入字段上使用 jquery 验证插件 因为内容是在 dom 上运行 jquery 验证之后加载的 所以
  • Glassfish 3.1.1 启动失败

    我正在运行 glassfish 3 1 1 在我的开发机器 使用 Windows XP 上运行了一段时间 但今天早上它无法启动 跑步asadmin start domain domain1它报告 Waiting for domain1 to
  • RequireJS 中的命名模块与未命名模块

    我们可以通过给它命名来在 requireJS 中创建一个模块 define name dep function dep module definition 或者我们可以创建一个不包含名称的 define dep function dep m
  • 隐藏水平滚动条(Angular ui-grid)

    我试图隐藏 Angular ui grid 的水平滚动条 但我找不到正确的属性 财产启用滚动条 假删除两者 是否可以只删除水平滚动条 使用 Github v3 0 0 rc 16 上的最新版本 您可以分别禁用水平和垂直滚动条 代替 enab
  • 为什么 Java 8 泛型类型推断选择这种重载?

    考虑以下程序 public class GenericTypeInference public static void main String args print new SillyGenericWrapper get private s
  • 使用水豚测试黄瓜中的饼干

    作为网站集成测试的一部分 我将黄瓜与水豚一起使用 水豚似乎无法模拟cookie的使用 例如 我在用户登录时设置 cookie def sign in user cookies permanent signed remember token
  • iOS UiWebView“帧加载中断”

    我有一个 UiWebView 指向一个外部站点 该站点的会话过期时间为 30 分钟不活动 在我的应用程序中 我在应用程序中嵌入了一个自定义登录页面 因为我无法使用远程站点的登录页面 这个登录页面是 file index html 当用户将应
  • 包(Python PIL/Pillow)已安装,但我无法导入它

    我想做一些图像处理 但遇到了问题 导入枕头模块似乎不起作用 我在这里找到了一个简单的脚本来检查安装了哪些软件包 我找到了它 但导入它似乎不起作用 这是我尝试运行的代码 import pip installed packages pip ge
  • SignalR cookie 未从客户端发送

    我有一个从客户端发送的 cookie 用作我的 MVC Web 服务的一部分 但是现在我已将集线器集成到此应用程序中 集线器不会发送 cookie 而 mvc 应用程序会发送该 cookie 现在 在阅读其他类似的问题 不是很多 后 coo
  • Little Endian 并推入 nasm

    我不明白为什么代码的输出是Ole 小字节序不应该影响push命令 global start section data x dd 3 section text start mov eax 4 mov ebx 1 mov dword x 0x0
  • C++: std::tie 与 std::ignore 的返回类型

    我想知道 C 11 标准是否给出了关于type of the std tuple由返回std tie当一些论点是std ignore 更具体地说 我可以假设 decltype std tie 42 std ignore 不等于decltyp
  • 64 位 Microsoft SQL Server 数据工具

    我无法找到 64 位版本的 Microsoft SQL Server Data Tools 有谁知道哪里可以下载64位版本Microsoft SQL Server 数据工具 Visual Studio 2013 和 SQL Server 2
  • 在 Swift 中检查 iOS 设备是否有 LiDAR

    Swift 有没有办法检查设备是否有 LiDAR 传感器 不幸的是 我在苹果官方纪录片和互联网搜索中都没有找到任何信息 我当前的解决方法是确定设备类型 如本文中所述 如何确定当前的iPhone 设备型号 https stackoverflo
  • Sencha Touch 2 - 无法从控制器获取参考视图

    我正在尝试通过参考查看 在控制器中定义的方法内 我收到错误消息 对象 object Object 没有方法 getUserForm 这是我的视图和控制器 如果有人可以帮助我 我会很高兴 提前致谢 用户表格 Ext define appNam
  • .htaccess url重写

    我想重写一个URL 假设您访问http files domain com uploads file name jpg http files domain com uploads file name jpg 我如何使用 htaccess 来编
  • Python - 导入函数和本地声明函数之间的性能差异?

    在 Python 中导入函数与在当前文件中声明函数在性能上是否存在显着差异 我有一个小函数 单行 我经常在几个函数中使用它 py我的程序中的文件 我希望只定义一次 以便我对它所做的更改反映在各处 但是 我不确定将它用作导入函数是否会在调用它
  • 使 (Mac)Vim 重新打开并在关闭时打开文件

    使用案例 MacVim 窗口中显示 2 3 个文件 您按 ctrl Q MacVim 就会关闭 当您重新启动 MacVim 时 它会打开并显示与您关闭它时相同的文件 你怎么能这么做呢 ANSWER 我将以下内容添加到我的 vmirc sav
  • 组合 Spark UDF(而不是将 UDF 作为一个)时是否会造成性能损失?

    我想知道编写 Spark udf 是否会降低性能 一般来说 我更喜欢编写只做一件事的小函数 这是一个简单的例子 给定一个DataFrame df def inc udf i Double gt i 1 def double udf i Do