欧美中文字幕第一页-欧美中文字幕一区-欧美中文字幕一区二区三区-欧美中文字幕在线-欧美中文字幕在线播放-欧美中文字幕在线视频

且談Apache Spark的API三劍客:RDD、DataFrame和Dataset-36大數(shù)據(jù)

我是創(chuàng)始人李巖:很抱歉!給自己產(chǎn)品做個(gè)廣告,點(diǎn)擊進(jìn)來(lái)看看。  

且談Apache Spark的API三劍客:RDD、DataFrame和Dataset-36大數(shù)據(jù)

作者: Jules S. Damji?

最令開(kāi)發(fā)者們高興的事莫過(guò)于有一組API,可以大大提高開(kāi)發(fā)者們的工作效率,容易使用、非常直觀并且富有表現(xiàn)力。Apache Spark廣受開(kāi)發(fā)者們歡迎的一個(gè)重要原因也在于它那些非常容易使用的API,可以方便地通過(guò)多種語(yǔ)言,如Scala、Java、Python和R等來(lái)操作大數(shù)據(jù)集。

在本文中,我將深入講講Apache Spark 2.2以及以上版本提供的三種API——RDD、DataFrame和Dataset,在什么情況下你該選用哪一種以及為什么,并概述它們的性能和優(yōu)化點(diǎn),列舉那些應(yīng)該使用DataFrame和Dataset而不是RDD的場(chǎng)景。我會(huì)更多地關(guān)注DataFrame和Dataset,因?yàn)樵贏pache Spark 2.0中這兩種API被整合起來(lái)了。

這次整合背后的動(dòng)機(jī)在于我們希望可以讓使用Spark變得更簡(jiǎn)單,方法就是減少你需要掌握的概念的數(shù)量,以及提供處理結(jié)構(gòu)化數(shù)據(jù)的辦法。在處理結(jié)構(gòu)化數(shù)據(jù)時(shí),Spark可以像針對(duì)特定領(lǐng)域的語(yǔ)言所提供的能力一樣,提供高級(jí)抽象和API。

彈性分布式數(shù)據(jù)集(Resilient Distributed Dataset,RDD)

從一開(kāi)始RDD就是Spark提供的面向用戶的主要API。從根本上來(lái)說(shuō),一個(gè)RDD就是你的數(shù)據(jù)的一個(gè)不可變的分布式元素集合,在集群中跨節(jié)點(diǎn)分布,可以通過(guò)若干提供了轉(zhuǎn)換和處理的底層API進(jìn)行并行處理。

在什么情況下使用RDD?

下面是使用RDD的場(chǎng)景和常見(jiàn)案例:

  • 你希望可以對(duì)你的數(shù)據(jù)集進(jìn)行最基本的轉(zhuǎn)換、處理和控制;
  • 你的數(shù)據(jù)是非結(jié)構(gòu)化的,比如流媒體或者字符流;
  • 你想通過(guò)函數(shù)式編程而不是特定領(lǐng)域內(nèi)的表達(dá)來(lái)處理你的數(shù)據(jù);
  • 你不希望像進(jìn)行列式處理一樣定義一個(gè)模式,通過(guò)名字或字段來(lái)處理或訪問(wèn)數(shù)據(jù)屬性;
  • 你并不在意通過(guò)DataFrame和Dataset進(jìn)行結(jié)構(gòu)化和半結(jié)構(gòu)化數(shù)據(jù)處理所能獲得的一些優(yōu)化和性能上的好處;

Apache Spark 2.0中的RDD有哪些改變?

?可能你會(huì)問(wèn):RDD是不是快要降級(jí)成二等公民了?是不是快要退出歷史舞臺(tái)了?

答案是非常堅(jiān)決的:

而且,接下來(lái)你還將了解到,你可以通過(guò)簡(jiǎn)單的API方法調(diào)用在DataFrame或Dataset與RDD之間進(jìn)行無(wú)縫切換,事實(shí)上DataFrame和Dataset也正是基于RDD提供的。

DataFrame

與RDD相似,DataFrame也是數(shù)據(jù)的一個(gè)不可變分布式集合。但與RDD不同的是,數(shù)據(jù)都被組織到有名字的列中,就像關(guān)系型數(shù)據(jù)庫(kù)中的表一樣。設(shè)計(jì)DataFrame的目的就是要讓對(duì)大型數(shù)據(jù)集的處理變得更簡(jiǎn)單,它讓開(kāi)發(fā)者可以為分布式的數(shù)據(jù)集指定一個(gè)模式,進(jìn)行更高層次的抽象。它提供了特定領(lǐng)域內(nèi)專用的API來(lái)處理你的分布式數(shù)據(jù),并讓更多的人可以更方便地使用Spark,而不僅限于專業(yè)的數(shù)據(jù)工程師。

在我們的Apache Spark 2.0網(wǎng)絡(luò)研討會(huì)以及后續(xù)的博客中,我們提到在Spark 2.0中,DataFrame和Dataset的API將融合到一起,完成跨函數(shù)庫(kù)的數(shù)據(jù)處理能力的整合。在整合完成之后,開(kāi)發(fā)者們就不必再去學(xué)習(xí)或者記憶那么多的概念了,可以通過(guò)一套名為Dataset的高級(jí)并且類(lèi)型安全的API完成工作。

且談Apache Spark的API三劍客:RDD、DataFrame和Dataset-36大數(shù)據(jù)

Dataset

如下面的表格所示,從Spark 2.0開(kāi)始,Dataset開(kāi)始具有兩種不同類(lèi)型的API特征:有明確類(lèi)型的API和無(wú)類(lèi)型的API。從概念上來(lái)說(shuō),你可以把DataFrame當(dāng)作一些通用對(duì)象Dataset[Row]的集合的一個(gè)別名,而一行就是一個(gè)通用的無(wú)類(lèi)型的JVM對(duì)象。與之形成對(duì)比,Dataset就是一些有明確類(lèi)型定義的JVM對(duì)象的集合,通過(guò)你在Scala中定義的Case Class或者Java中的Class來(lái)指定。

有類(lèi)型和無(wú)類(lèi)型的API

且談Apache Spark的API三劍客:RDD、DataFrame和Dataset-36大數(shù)據(jù)

注意:因?yàn)镻ython和R沒(méi)有編譯時(shí)類(lèi)型安全,所以我們只有稱之為DataFrame的無(wú)類(lèi)型API。

Dataset API的優(yōu)點(diǎn)

在Spark 2.0里,DataFrame和Dataset的統(tǒng)一API會(huì)為Spark開(kāi)發(fā)者們帶來(lái)許多方面的好處。

1、靜態(tài)類(lèi)型與運(yùn)行時(shí)類(lèi)型安全

從SQL的最小約束到Dataset的最嚴(yán)格約束,把靜態(tài)類(lèi)型和運(yùn)行時(shí)安全想像成一個(gè)圖譜。比如,如果你用的是Spark SQL的查詢語(yǔ)句,要直到運(yùn)行時(shí)你才會(huì)發(fā)現(xiàn)有語(yǔ)法錯(cuò)誤(這樣做代價(jià)很大),而如果你用的是DataFrame和Dataset,你在編譯時(shí)就可以捕獲錯(cuò)誤(這樣就節(jié)省了開(kāi)發(fā)者的時(shí)間和整體代價(jià))。也就是說(shuō),當(dāng)你在DataFrame中調(diào)用了API之外的函數(shù)時(shí),編譯器就可以發(fā)現(xiàn)這個(gè)錯(cuò)。不過(guò),如果你使用了一個(gè)不存在的字段名字,那就要到運(yùn)行時(shí)才能發(fā)現(xiàn)錯(cuò)誤了。

圖譜的另一端是最嚴(yán)格的Dataset。因?yàn)镈ataset API都是用lambda函數(shù)和JVM類(lèi)型對(duì)象表示的,所有不匹配的類(lèi)型參數(shù)都可以在編譯時(shí)發(fā)現(xiàn)。而且在使用Dataset時(shí),你的分析錯(cuò)誤也會(huì)在編譯時(shí)被發(fā)現(xiàn),這樣就節(jié)省了開(kāi)發(fā)者的時(shí)間和代價(jià)。

所有這些最終都被解釋成關(guān)于類(lèi)型安全的圖譜,內(nèi)容就是你的Spark代碼里的語(yǔ)法和分析錯(cuò)誤。在圖譜中,Dataset是最嚴(yán)格的一端,但對(duì)于開(kāi)發(fā)者來(lái)說(shuō)也是效率最高的。

且談Apache Spark的API三劍客:RDD、DataFrame和Dataset-36大數(shù)據(jù)

2、關(guān)于結(jié)構(gòu)化和半結(jié)構(gòu)化數(shù)據(jù)的高級(jí)抽象和定制視圖

把DataFrame當(dāng)成Dataset[Row]的集合,就可以對(duì)你的半結(jié)構(gòu)化數(shù)據(jù)有了一個(gè)結(jié)構(gòu)化的定制視圖。比如,假如你有個(gè)非常大量的用JSON格式表示的物聯(lián)網(wǎng)設(shè)備事件數(shù)據(jù)集。因?yàn)镴SON是半結(jié)構(gòu)化的格式,那它就非常適合采用Dataset來(lái)作為強(qiáng)類(lèi)型化的Dataset[DeviceIoTData]的集合。

{"device_id": 198164, "device_name": "sensor-pad-198164owomcJZ", "ip": "80.55.20.25", "cca2": "PL", "cca3": "POL", "cn": "Poland", "latitude": 53.080000, "longitude": 18.620000, "scale": "Celsius", "temp": 21, "humidity": 65, "battery_level": 8, "c02_level": 1408, "lcd": "red", "timestamp" :1458081226051}

你可以用一個(gè)Scala Case Class來(lái)把每條JSON記錄都表示為一條DeviceIoTData,一個(gè)定制化的對(duì)象。

				case class DeviceIoTData (battery_level: Long, c02_level: Long, cca2:
				String, cca3: String, cn: String, device_id: Long, device_name: String, humidity:
				Long, ip: String, latitude: Double, lcd: String, longitude: Double, scale:String, temp: Long, timestamp: Long)
			

接下來(lái),我們就可以從一個(gè)JSON文件中讀入數(shù)據(jù)。

				// read the json file and create the dataset from the
				// case class DeviceIoTData
				// ds is now a collection of JVM Scala objects DeviceIoTData
				val ds = spark.read.json(“/databricks-public-datasets/data/iot/iot_devices.json”).as[DeviceIoTData]
			

上面的代碼其實(shí)可以細(xì)分為三步:

  1. Spark讀入JSON,根據(jù)模式創(chuàng)建出一個(gè)DataFrame的集合;
  2. 在這時(shí)候,Spark把你的數(shù)據(jù)用“DataFrame = Dataset[Row]”進(jìn)行轉(zhuǎn)換,變成一種通用行對(duì)象的集合,因?yàn)檫@時(shí)候它還不知道具體的類(lèi)型;
  3. 然后,Spark就可以按照類(lèi)DeviceIoTData的定義,轉(zhuǎn)換出“Dataset[Row] -> Dataset[DeviceIoTData]”這樣特定類(lèi)型的Scala JVM對(duì)象了。

許多和結(jié)構(gòu)化數(shù)據(jù)打過(guò)交道的人都習(xí)慣于用列的模式查看和處理數(shù)據(jù),或者訪問(wèn)對(duì)象中的某個(gè)特定屬性。將Dataset作為一個(gè)有類(lèi)型的Dataset[ElementType]對(duì)象的集合,你就可以非常自然地又得到編譯時(shí)安全的特性,又為強(qiáng)類(lèi)型的JVM對(duì)象獲得定制的視圖。而且你用上面的代碼獲得的強(qiáng)類(lèi)型的Dataset[T]也可以非常容易地用高級(jí)方法展示或處理。

且談Apache Spark的API三劍客:RDD、DataFrame和Dataset-36大數(shù)據(jù)

3、方便易用的結(jié)構(gòu)化API

雖然結(jié)構(gòu)化可能會(huì)限制你的Spark程序?qū)?shù)據(jù)的控制,但它卻提供了豐富的語(yǔ)義,和方便易用的特定領(lǐng)域內(nèi)的操作,后者可以被表示為高級(jí)結(jié)構(gòu)。事實(shí)上,用Dataset的高級(jí)API可以完成大多數(shù)的計(jì)算。比如,它比用RDD數(shù)據(jù)行的數(shù)據(jù)字段進(jìn)行agg、select、sum、avg、map、filter或groupBy等操作簡(jiǎn)單得多,只需要處理Dataset類(lèi)型的DeviceIoTData對(duì)象即可。

用一套特定領(lǐng)域內(nèi)的API來(lái)表達(dá)你的算法,比用RDD來(lái)進(jìn)行關(guān)系代數(shù)運(yùn)算簡(jiǎn)單得多。比如,下面的代碼將用filter()和map()來(lái)創(chuàng)建另一個(gè)不可變Dataset。

				// Use filter(), map(), groupBy() country, and compute avg()
				// for temperatures and humidity. This operation results in
				// another immutable Dataset. The query is simpler to read,
				// and expressive
				val dsAvgTmp = ds.filter(d => {d.temp > 25}).map(d => (d.temp, d.humidity, d.cca3)).groupBy($"_3").avg()
				//display the resulting dataset
				display(dsAvgTmp)
			

且談Apache Spark的API三劍客:RDD、DataFrame和Dataset-36大數(shù)據(jù)

4、性能與優(yōu)化

除了上述優(yōu)點(diǎn)之外,你還要看到使用DataFrame和Dataset API帶來(lái)的空間效率和性能提升。原因有如下兩點(diǎn):

首先,因?yàn)镈ataFrame和Dataset API都是基于Spark SQL引擎構(gòu)建的,它使用Catalyst來(lái)生成優(yōu)化后的邏輯和物理查詢計(jì)劃。所有R、Java、Scala或Python的DataFrame/Dataset API,所有的關(guān)系型查詢的底層使用的都是相同的代碼優(yōu)化器,因而會(huì)獲得空間和速度上的效率。盡管有類(lèi)型的Dataset[T] API是對(duì)數(shù)據(jù)處理任務(wù)優(yōu)化過(guò)的,無(wú)類(lèi)型的Dataset[Row](別名DataFrame)卻運(yùn)行得更快,適合交互式分析。

且談Apache Spark的API三劍客:RDD、DataFrame和Dataset-36大數(shù)據(jù)

其次,Spark作為一個(gè)編譯器,它可以理解Dataset類(lèi)型的JVM對(duì)象,它會(huì)使用編碼器來(lái)把特定類(lèi)型的JVM對(duì)象映射成Tungsten的內(nèi)部?jī)?nèi)存表示。結(jié)果,Tungsten的編碼器就可以非常高效地將JVM對(duì)象序列化或反序列化,同時(shí)生成壓縮字節(jié)碼,這樣執(zhí)行效率就非常高了。

該什么時(shí)候使用DataFrame或Dataset呢?

  • 如果你需要豐富的語(yǔ)義、高級(jí)抽象和特定領(lǐng)域?qū)S玫腁PI,那就使用DataFrame或Dataset;
  • 如果你的處理需要對(duì)半結(jié)構(gòu)化數(shù)據(jù)進(jìn)行高級(jí)處理,如filter、map、aggregation、average、sum、SQL查詢、列式訪問(wèn)或使用lambda函數(shù),那就使用DataFrame或Dataset;
  • 如果你想在編譯時(shí)就有高度的類(lèi)型安全,想要有類(lèi)型的JVM對(duì)象,用上Catalyst優(yōu)化,并得益于Tungsten生成的高效代碼,那就使用Dataset;
  • 如果你想在不同的Spark庫(kù)之間使用一致和簡(jiǎn)化的API,那就使用DataFrame或Dataset;
  • 如果你是R語(yǔ)言使用者,就用DataFrame;
  • 如果你是Python語(yǔ)言使用者,就用DataFrame,在需要更細(xì)致的控制時(shí)就退回去使用RDD;

注意只需要簡(jiǎn)單地調(diào)用一下.rdd,就可以無(wú)縫地將DataFrame或Dataset轉(zhuǎn)換成RDD。例子如下:

				// select specific fields from the Dataset, apply a predicate
				// using the where() method, convert to an RDD, and show first 10
				// RDD rows
				val deviceEventsDS = ds.select($"device_name", $"cca3", $"c02_level").where($"c02_level" > 1300)
				// convert to RDDs and take the first 10 rows
				val eventsRDD = deviceEventsDS.rdd.take(10)
			

且談Apache Spark的API三劍客:RDD、DataFrame和Dataset-36大數(shù)據(jù)

總結(jié)

總之,在什么時(shí)候該選用RDD、DataFrame或Dataset看起來(lái)好像挺明顯。前者可以提供底層的功能和控制,后者支持定制的視圖和結(jié)構(gòu),可以提供高級(jí)和特定領(lǐng)域的操作,節(jié)約空間并快速運(yùn)行。

當(dāng)我們回顧從早期版本的Spark中獲得的經(jīng)驗(yàn)教訓(xùn)時(shí),我們問(wèn)自己該如何為開(kāi)發(fā)者簡(jiǎn)化Spark呢?該如何優(yōu)化它,讓它性能更高呢?我們決定把底層的RDD API進(jìn)行高級(jí)抽象,成為DataFrame和Dataset,用它們?cè)贑atalyst優(yōu)化器和Tungsten之上構(gòu)建跨庫(kù)的一致數(shù)據(jù)抽象。

DataFrame和Dataset,或RDD API,按你的實(shí)際需要和場(chǎng)景選一個(gè)來(lái)用吧,當(dāng)你像大多數(shù)開(kāi)發(fā)者一樣對(duì)數(shù)據(jù)進(jìn)行結(jié)構(gòu)化或半結(jié)構(gòu)化的處理時(shí),我不會(huì)有絲毫驚訝。

End.

轉(zhuǎn)載請(qǐng)注明來(lái)自36大數(shù)據(jù)(36dsj.com): 36大數(shù)據(jù) ? 且談Apache Spark的API三劍客:RDD、DataFrame和Dataset

隨意打賞

apache spark
提交建議
微信掃一掃,分享給好友吧。
主站蜘蛛池模板: 成人欧美一区二区三区黑人免费 | 国产精品一区二区免费 | 手机看高清特黄a大片 | 狠狠久久综合伊人不卡 | 久久久久久夜精品精品免费啦 | 天天操天天干天天操 | 精品成人一区二区三区免费视频 | 国产精品视频国产永久视频 | 伊人99| 国产综合久久一区二区三区 | 久草久热| 深夜福利剧场 | 深夜免费视频 | 久久se精品一区二区国产 | 亚洲精品久久久久综合中文字幕 | 国产三级日产三级日本三级 | 免费鲁丝片一级在线观看 | 97精品在线播放 | 成年女人毛片免费视频 | 亚洲12色吧 | 亚洲天堂一区二区三区 | 黄色直接观看 | 欧美毛片一级的免费的 | 日本高清免费视频不卡a | 成人影院久久久久久影院 | 好看的亚洲视频 | 四虎欧美 | 亚洲免费视频在线观看 | 六月丁香色婷婷 | 亚洲人成在线观看 | 欧美一级毛片免费大片 | 综合久久久久久中文字幕 | 婷婷六月天激情 | 蕾丝视频永久在线入口香蕉 | 亚洲精品另类 | 久草在线国产视频 | 性欧美精品久久久久久久 | 久久99久久99精品免观看麻豆 | 欧美成人毛片在线视频 | 成人私人影院在线观看网址 | 成人午夜爱爱爱爱爱 |