前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >实战|一群人齐心协力解决了一个spark问题

实战|一群人齐心协力解决了一个spark问题

作者头像
麒思妙想
发布2020-07-10 13:15:48
5000
发布2020-07-10 13:15:48
举报
文章被收录于专栏:麒思妙想麒思妙想

首先感谢 spark君 细心的整理,下文是早些时候在群里关于一个SparkSQL条件下推问题的实录,由于刚刚发表了一篇文章(Flink SQL vs Spark SQL),正好对这块理解还是热乎的,所以我作为D君,我也混水摸了一下鱼。

在阅读正文之前,大家再看一眼这幅图,应该会对理解下文有所帮助。

----------------------------------华丽得分割线---------------------------

spark君前段时间组织了一波学习社区,没过几天竟然增加到了人数增加230多个人。

大家在社区里面是互利互助的关系,如果只索取不分享对社区其他小伙伴是不公平的,有很多人入群后,就深度潜水了,这样的话我可能认为这个社区对你没有什么价值,你对这个社区其他成员也没有价值,所以上周末一口气踢掉了60多个人,也全部从知识星球里面也移除了,现在我也懒得踢人了,进入社区也提了提门槛,想进入学习社区必须有平时有总结分享知识点的习惯,先发一篇自己整理的东西,就是平时解决了啥问题,一段话描述问题解决方案和思路,或者看到的什么知识点记录,或者之前收集的一些学习资料,面试资料,大数据或者AI相关的都行,不用很全很完整的东西,只要能看到你认真整理分享的态度就行。

还有另外一个问题就有些人总是习惯于无脑地甩报错截图,能问别人的绝不google,这种人我认为你是对别人时间的不尊重,在社区里面提问题要讲究提问题的艺术:

碰到问题的时候先去google,先尽自己最大能力解决问题,如果解决不了,提问题的时候,说清楚前因后果,详细的描述信息,不要让回答者感觉问题很模棱两可,加上问题的各种前提条件,自己尝试过哪些方案,想要达到什么目标,自己卡住的关键点,抓住重点,不要问太泛太大的问题,这种一般没法回答。

以上都是题外话,这两天有人在社区里面提了一个问题,我觉得可以给大家分享一下:

问题君:

我今天通过pyspark去读取kudu表的数据,然后做了一个filter(pt=20190301 and courier_mobile='xxxxxxx'),在filter的时候由于字段类型错误(本来是pt="123",我错写成pt=123,pt是分区字段,string类型),导致了全表扫描,很久都没跑出来结果

上面这种提问题的方式spark 君觉得也还是ok的,最起码清晰描述出来了问题的基本情况

A君给的建议:

你是想看看你写的程序底层有没有做全表扫描么,可以看执行计划吧

提问君:

我对比下前后两次explain()有什么区别吧

然后过了一会给出了两种不同写法的执行计划

错误情况:

正确情况:

两种的区别好像就是 错误写法的Filter 没有下推到Scan 操作里面,而且Filter的谓词表达式里面多了一个类型转换

C君给的回答:

我记得sparksql的优化中有个东西叫做谓语下移 我想应该是这样的

如果是pt=“sadsa” string与string比较的话 他会优化语法 将 fliter--在sql中有点像where这样的谓语下移到scan表格的时候直接过滤掉 将scan和filter合成一步操作

如果是pt=12311 string与int比较的话 他就不会做优化 会先scan所有 再拿pt的数据转换成int在与12311对比 scan和fliter会分成两步操作

这个只是猜想 你可以考虑下这种情况

D君:

赞成,应该是类型不匹配的时候,优化器没降条件下推,而是自己来过滤了

问题君:

你说的这种情况感觉是符合逻辑的

在错误情况下

1、 想kudu发送命令,依据另一个courier_mobile的条件,从kudu中查询所有数据,这里courier_mobile不是分区字段,kudu里面全表扫描,这一布非常非常慢

2、 spark拿到第一步的结果,在内存里面做filter

C君竟然神奇的搞出来一个图,也不知道从哪来搞来的,还是现成话的,佩服:

。。。。。

经过一番激烈的讨论,大家达成了一致,就是因为过滤的时候Filter 对比的数据类型,跟数据库kudu中字段的类型不一致,导致字段需要转换,然后这个谓词下推就没法下推的数据库层面去过滤,导致了全表扫描,拉取全部数据,然后在spark这边进行过滤。

这时候spark君本人也来了兴致,开始装逼:

撸了很长时间源码,发现问题出在逻辑执行计划变为物理执行计划这一步

在 DataSourceStrategy类 -> pruneFilterProjectRaw ->selectFilters -> translateFilter 这个方法上面,

这个方法中会对 Filter算子的谓词表达式进行过滤,使用模式匹配,把一些不能下推到数据库的Filter给过滤掉,可以下推的谓词表达式过滤出来,下推到数据库来执行过滤操作

spark 君分分钟写了单测,然后经过漫长的spark源码build过程,debug 发现两种写法传递到这里的谓词表达式果然不同

错误写法: "SELECT a, b FROM test1 WHERE pt = 20190301"

传递到这里的 谓词表达式是: cast(pt#2 as int) = 20190301

正确写法: "SELECT a, b FROM test1 WHERE pt = '20190301'"

传递到这里的 谓词表达式是:(pt#2 = 20190301)

在过滤的模式匹配中只会匹配两种 :

EqualTo(变量,常量)

EqualTo(常量,变量)

所以错误写法被过滤掉,不会下推到数据库去执行过滤

到此为止,一个问题就真相大白了,大家都从中学到了很多东西,棒棒哒

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 麒思妙想 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档