如题所示,SparkSQL /DataFrame /Spark RDD谁快?

按照官方宣传以及大部分人的理解,SparkSQL和DataFrame虽然基于RDD,但是由于对RDD做了优化,所以性能会优于RDD。

之前一直也是这么理解和操作的,直到最近遇到了一个场景,打破了这种不太准确的认识。

某些场景下,RDD要比DataFrame快,性能有天壤之别。

需求如下

以下两份数据求交集,结果输出url。

数据一,json格式,地址我们用path_json表示,大小10T,每一行数据格式:{"id":"md5字符串", "url":"https://www.thesaurus.com/","title":"sysnonyms and antonyms",xxx},大概20来个字段;

数据二,csv格式,地址我们用path_csv表示,大小50G,每一行数据格式:name url,2个字段,用\t隔开。

拿到需求后,迅速瞟了一眼数据,爽快答应需求方分分钟搞定。

此时此刻,必须得祭出宇宙Top N的IDE,结合我30多年的人生阅历和代码经验,瞬间雷光电扇,惊雷骤起,一顿操作猛如虎,天空飘过以下几行代码:

(老铁们,请自行安装python,pyspark,pycharm)

方案一


from pyspark.sql import SparkSession
def join_it():
path_json = 'hdfs://i/love/you/' # 数据大小10T, 5万分区
path_csv = 'hdfs://you/love/me' # 数据大小50G
path_save = 'hdfs://we/are/together' df1 = spark.read.json(path_json).select('url')
df2 = spark.read.option('sep', '\t').schema('name string, url string').csv(path_csv)
df1.join(df2) \
.select(df1.url)\
.coalesce(10000) \
.write \
.mode('overwrite') \
.option('sep', '\t') \
.csv(path_save) if __name__ == '__main__':
spark = SparkSession.builder.appName('pyspark').getOrCreate()
sc = spark.sparkContext
sc.setLogLevel("ERROR")
#
join_it()
#
spark.stop()

spark-submit提交任务到spark集群,参数根据自己的实际情况自行修改。

spark-submit \
--master yarn \
--deploy-mode client \
--name 'i-live-you' \
--queue 'you-love-me' \
--driver-cores \
--driver-memory 30g \
--num-executors \
--executor-memory 30g \
--executor-cores \
--archives 'hdfs://your-python-path-on-hdfs#pkg'
--conf spark.yarn.appMasterEnv.PYSPARK_PYTHON='集群里面的python地址' \
--conf spark.sql.shuffle.partitions= \
--conf spark.default.parallelism= \
--conf spark.task.maxFailures= \
your-spark-script.py

如果需要在本机调试代码,spark的生成需要替换成如下,然后直接运行。调试通过后,仍然需要按照上述方式spark-submit提交任务到集群运行,由于数据量很大,需要在集群运行才能看出性能差异。

spark = SparkSession.builder.appName('pyspark').master('local[*]').getOrCreate()

又是一顿猛操作,提交任务后,嗡嗡叫的肚子提醒我,要去厕所烧一根香,拜拜佛,佛祖保佑无bug。

深圳的夏天,依旧不负众望的燥热。热情似火的太阳,伴着她最爱的紫外线和电磁波,循着外太空固定的轨道,迈着30万公里/秒的矫健步伐,到达这颗承载70亿人的蓝色星球,穿透层层蓝天白云,无私的照亮着广袤的深圳大地。

酷暑让人思想活跃,思绪万千。扯得有点远了,重来不重来了,接着写bug。

作为一个谨记厕所文化的人,蹲坑5分钟,方便你我他;蹲坑半小时,痔疮等着你。我选择了后者。

半小时过去了,时间随着大A股的大跌,瞬间来到了下午的收盘时间。果不其然,又一个下跌如期而至,就在这一刻,体内的混浊之气伴着伴随着收跌的股市排出体外。收拾干净后,我带着满身厕所的芬芳,回到了座位上。

再次打开电脑屏幕,spark任务还在慢悠悠的读取json文件,半小时才读取300G左右,10T的json文件按照这个速度,全部读完的好几天。此方案不可用。

方案二

果断改成RDD,然后用intersection求交集,果然快很多,10T跟50G求交集,12000cores,5分钟出结果。Spark任务提交同方案一,不再赘述。此方案可行

屁颠屁颠的把结果交付给需求方,大佬甚是满意地流出了开心的泪水

import json
from pyspark.sql import SparkSession def join_it():
path_json = 'hdfs://i/love/you/' # 数据大小10T, 5万分区
path_csv = 'hdfs://you/love/me' # 数据大小50G
path_save = 'hdfs://we/are/together'
#
rdd1 = sc.textFile(path_json).map(lambda v: json.loads(v).get('url', '')).coalesce(50000)
rdd2 = sc.textFile(path_csv).map(lambda v: v.split('\t')[1])
rdd1.intersection(rdd2).coalesce(20000).saveAsTextFile(path_save) if __name__ == '__main__':
spark = SparkSession.builder.appName('pyspark').getOrCreate()
sc = spark.sparkContext
sc.setLogLevel("ERROR")
#
join_it()
#
spark.stop()

方案三

离下班实际还有30分钟,作为一个对技术有追求的资深码农,尝试用SparkSQL实现该功能。祭出代码,以资各位看官共享,新能跟RDD不相上下。此方案也可取。

import json
from pyspark.sql import SparkSession def join_it():
path_json = 'hdfs://i/love/you/' # 数据大小10T, 5万分区
path_csv = 'hdfs://you/love/me' # 数据大小50G
path_save = 'hdfs://we/are/together'
#
sc.textFile(path_json).map(lambda v: (json.loads(v).get('url', ''),)).toDF(['url']).createOrReplaceTempView('a')
spark.read.option('sep', '\t').schema('name string, url string').csv(path_csv).createOrReplaceTempView('b') sql = '''
SELECT
a.url
FROM
a
JOIN
b
ON
a.url=b.url
'''
spark.sql(sql).coalesce(20000).write.mode('overwrite').option('sep', '\t').csv(path_save) if __name__ == '__main__':
spark = SparkSession.builder.appName('pyspark').getOrCreate()
sc = spark.sparkContext
sc.setLogLevel("ERROR")
#
join_it()
#
spark.stop()

总结:

当遇到源数据是体量比较大的json或其他格式的时候,不要用spark.read的形式直接导入到DataFrame。

那要咋弄?可以先用RDD把源数据加载进来,然后再转化成DataFrame,后面用SparkSQL进行操作,如此可达到较好的性能效果。

SparkSQL /DataFrame /Spark RDD谁快?的更多相关文章

  1. spark RDD,DataFrame,DataSet 介绍

    弹性分布式数据集(Resilient Distributed Dataset,RDD) RDD是Spark一开始就提供的主要API,从根本上来说,一个RDD就是你的数据的一个不可变的分布式元素集合,在 ...

  2. Spark大型电商项目实战-及其改良(1) 比对sparkSQL和纯RDD实现的结果

    代码存在码云:https://coding.net/u/funcfans/p/sparkProject/git 代码主要学习https://blog.csdn.net/u012318074/artic ...

  3. Spark RDD、DataFrame原理及操作详解

    RDD是什么? RDD (resilientdistributed dataset),指的是一个只读的,可分区的分布式数据集,这个数据集的全部或部分可以缓存在内存中,在多次计算间重用. RDD内部可以 ...

  4. [Spark][Python][RDD][DataFrame]从 RDD 构造 DataFrame 例子

    [Spark][Python][RDD][DataFrame]从 RDD 构造 DataFrame 例子 from pyspark.sql.types import * schema = Struct ...

  5. [Spark][Python][DataFrame][RDD]从DataFrame得到RDD的例子

    [Spark][Python][DataFrame][RDD]从DataFrame得到RDD的例子 $ hdfs dfs -cat people.json {"name":&quo ...

  6. Spark RDD、DataFrame和DataSet的区别

    版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   转载请标明出处:小帆的帆的专栏 RDD 优点: 编译时类型安全 编译时就能检查出类型错误 面向对象的编程风格 直接通过类 ...

  7. Spark SQL概念学习系列之DataFrame与RDD的区别

    不多说,直接上干货! DataFrame的推出,让Spark具备了处理大规模结构化数据的能力,不仅比原有的RDD转化方式更加简单易用,而且获得了更高的计算性能.Spark能够轻松实现从MySQL到Da ...

  8. Spark的dataframe转rdd通用工具类

    需求解决问题 当每次读取hive表或者其他数据源,获取数据,相对其进行rdd操作,遇到任何类都需要df.rdd(row>row.getstring(0))去获取,就很麻烦,所以可以实现个通用的转 ...

  9. 【Spark-SQL学习之二】 SparkSQL DataFrame创建和储存

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 scala-2.10.4(依赖jdk1.8) spark ...

随机推荐

  1. @RequestMapping中的produces的作用和使用方式

    转发:原博客 1.他的作用是指定返回值类型和返回值编码 2.consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html; 一 ...

  2. MySQL数据库---库的操作

    MySQL数据库中,以库,表,记录的形式管理所有的数据,安装MySQL数据库的服务器上可以包含多个库,一个库中包含多张表,一张表中包含多条记录.库对应的是文件系统中文件夹的概念,表对应的是文件的概念, ...

  3. [spring] -- AOP、IOC、DI篇

    AOP(面向切面编程) 怎么理解这个切面编程的概念及优点? 概念: 横切关注点与业务逻辑相分离,切面能帮助我们模块化横切关注点: 优点: 现在每个关注点都集中于一个地方,而不是分散到多处代码中: 服务 ...

  4. 从零开始学Electron笔记(七)

    在之前的文章我们介绍了一下Electron中的对话框 Dialog和消息通知 Notification,接下来我们继续说一下Electron中的系统快捷键及应用打包. 全局快捷键模块就是 global ...

  5. python---filecmp 实现文件,目录,遍历子目录的差异对比功能。

    python---filecmp ilecmp可以实现文件,目录,遍历子目录的差异对比功能. 自带filecmp模块,无需安装. 常用方法说明 filecmp提供3个操作方法,cmp(单文件对比),c ...

  6. Day01_虚拟化架构与系统部署

    学于千峰教育开源课程 感恩 千峰教育官网 b站在线视频 前言:本人所使用的操作系统是MacOS 使用的虚拟机软件为parallels desktop 本章结构 构建桌面端虚拟环境 虚拟机的概述 VMa ...

  7. matplotlib绘制子图

    fig,subs = plt.subplots(2,2) subs[0][0].plot(data_math_C1) subs[0][0].set_title('C_1 曲线') subs[0][1] ...

  8. Python raw_input() 函数

    python raw_input() 用来获取控制台的输入.高佣联盟 www.cgewang.com raw_input() 将所有输入作为字符串看待,返回字符串类型. 注意:input() 和 ra ...

  9. C/C++编程笔记:C语言贪吃蛇源代码控制台(一),会动的那种哦!

    前几天有个同学加我QQ私聊我说他们老师布置了一个贪吃蛇,他不知道怎么写所以来找我求解,我给他简单讲解了思路和一些难点之后他也能够自己独立将项目完成了!考虑到更多同学可能有贪吃蛇上的问题,今天有时间就来 ...

  10. java多线程的问题

    1.多线程有什么用 (1) 发挥多核CPU的优势 单核CPU上所谓的"多线程"那是假的多线程,同一时间处理器只会处理一段逻辑,只不过线程之间切换得比较快,看着像多个线程" ...