java case when用法_sql case when 嵌套

java case when用法_sql case when 嵌套前几天在客户环境遇到一个Spark“CASEWHEN”语句的性能优化问题。客户那边通过一个“时间范围筛选”控件来动态修改图表的数据。其很多指标的计算逻辑类似于:CASEWHEN`bizdate`BETWEEN’2020-09-06’AND’2020-09-13’THEN`sales_amount`ELSE0ENDCASEWHEN语句有些类似于编程语言中的Switch语句,当这里的…


Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

前几天在客户环境遇到一个Spark “CASE WHEN”语句的性能优化问题。

客户那边通过一个“时间范围筛选”控件来动态修改图表的数据。其很多指标的计算逻辑类似于:

CASE

WHEN `bizdate`

BETWEEN ‘2020-09-06’ AND ‘2020-09-13’

THEN `sales_amount`

ELSE 0

END

CASE WHEN语句有些类似于编程语言中的Switch语句,当这里的 WHEN从句只有一个的时候,可以简化为IF语句(或者 IF-ELSE 语句)。

于是想:对于Spark(客户用的是2.4.x版本), Spark会不会把这种只有一个WHEN分支的 CASE WHEN 语句优化为IF语句呢? 于是试了一下性能,发现如果修改上面的SQL为:

IF(`bizdate`

BETWEEN ‘2020-09-06’ AND ‘2020-09-13’,

`sales_amount`,

0

)

那么执行速度将减少为原来的一半! 原来Spark 2.4并没有做这个优化,突然感到有些兴奋。那是不是我的机会来了。

首先、这个应该是一个比较简单的优化,比如我是否可以通过增加一个Spark的优化器规则,来自动把一个分支的CASE WHEN转为IF,看着好像不难。

不过在真正动手前,先看看: Spark的最新版本是否已经有了这个修改?

于是先看看 CASE When 语句的实现,发现最新的发布版本(Spark 3.0.1)的代码是这样的:

override def doGenCode(ctx: CodegenContext,

ev: ExprCode): ExprCode = {

if (branches.length == 1) {

// If we have only single branch we can use If expression and its codeGen If(

branches(0)._1,

branches(0)._2,

elseValue

.getOrElse(Literal.create(null, branches(0)._2.dataType)))

.doGenCode(ctx, ev)

} else {

multiBranchesCodegen(ctx, ev)

}

}

发现,在Spark转化执行代码为 Java时(doGenCode),其已经对于分支为1的情况,做了自动转化为 IF 语句的操作。

虽然我感觉更适合放在优化器中做,不过直接修改 CaseWhen 这个类的 doGenCode() 可能简单直接! 从这个修改的PR的diff来看也确实如此(只改了几行代码):

首先,发现其 “Fix Version/s: 3.0.0”,果然是3.0才优化的。

其描述问题时的重现步骤:

val df = spark.range(10000000000L).withColumn(“x”, rand)

val resultA = df.withColumn(“r”, when($”x” < 0.5, lit(1)).otherwise(lit(0))).agg(sum($”r”))

val resultB = df.withColumn(“r”, expr(“if(x < 0.5, 1, 0)”)).agg(sum($”r”))

resultA.collect() // takes 56s to finishresultB.collect() // takes 30s to finish

发现其在spark旧版本中 IF 比 CaseWhen 要快很多 (30秒 vs 56秒)

虽然没有为Spark贡献成,但是也了解到了Spark 3.0的一些细节优化已经可以解决现在的一些实际问题了,Spark 3.0.1 值得期待应用到产品中!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/196875.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • shift后门结论_连续五次shift

    shift后门结论_连续五次shift经常会看到一些服务器被入侵后,入侵者会留下一些各式各样的shift后门,五花八门的,各位网络管理员也看看自己的服务器的setch.exe是否被人替换了。这个直接5次shift后进入分区这个比较巧妙了,正常的最后那个按钮是灰色的,前两个是不可点击的,这个恰恰想法,点击后,会弹出一个cmd窗口。这个是比较常见的需要输…

    2022年9月18日
  • PNP和NPN的区别_pnp和npn的二极管图

    PNP和NPN的区别_pnp和npn的二极管图为什么PNP三极管集电极(C)和发射极(E)反着接,却可以当开关使用?理解NPN和PNP两种类型的三极管原理及电流方向就会明白为什么PNP三极管的集电极和发射极反着接当开关使用。NPN和PNP三极

    2022年8月5日
  • 微信开放平台扫码登录[通俗易懂]

    微信开放平台扫码登录[通俗易懂]微信开放平台扫码登录的功能只有已经认证过的微信公众号才可以使用,很多学习微信的同学可能没办法使用这个功能,但是别担心,以下网址中有很多账号可以使用:【想要获取更多公众账号可以关注微信公众号:小D课堂】https://mp.weixin.qq.com/s?__biz=MzUyMDg1MDE2MA%3D%3D&amp;idx=2&amp;mid=2247483689&amp;sn=5…

    2022年6月14日
  • WebStorm常用快捷键(Mac版)

    WebStorm常用快捷键(Mac版)⌘——Command⌃——Control⌥——alt⇧——Shift⇪——CapsLockfn——功能键就是fn编辑Command+alt+T用(if..else,try..catch,for,etc.)包住Command+/注释/取消注释的行注释Command+alt+/注释/取消注释与块注释alt+↑向上选取代码块alt+↓向下选取代码块Command+alt+L格式化代码tab,shift+tab调整缩进Control+alt+I快

    2022年5月27日
  • Mysql表分区(diskgenius分区教程)

    Mysql表分区(diskgenius分区教程)一、MySQL分区表介绍分区是一种表的设计模式,正确的分区可以极大地提升数据库的查询效率,完成更高质量的SQL编程。但是如果错误地使用分区,那么分区可能带来毁灭性的的结果。分区功能并不是在存储引擎层完成的,因此不只有InnoDB存储引擎支持分区,常见的存储引擎MyISAM、NDB等都支持分区。但是并不是所有的存储引擎都支持,如CSV、FEDORATED、MERGE等就不支持分区。在

    2022年4月18日
  • 搭建J2ME开发平台

    搭建J2ME开发平台 1.导入设备定义你必须至少配置一种设备定义之后才能开始使用EclipseME。请按下列步骤来配置设备定义:从Eclipse的窗口菜单中选择首选项。打开左边面板的J2ME选项分支,点击设备管理(DeviceManagement)。 按导入…(Import)按钮。在接下来的对话框中,选择一个包含无线工具包的根目录,EclipseME将从中查找已知设备定

    2022年7月11日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号