通過(guò)本書(shū),你可以了解到:Spark SQL的新接口如何為SQL的RDD數(shù)據(jù)結(jié)構(gòu)提升性能。Spark Core與Spark SQL中數(shù)據(jù)join的不同選擇方式。充分利用標(biāo)準(zhǔn)RDD轉(zhuǎn)換的技術(shù)。如何解決Spark中鍵值范式的性能問(wèn)題。不借助Scala或其他JVM語(yǔ)言來(lái)編寫(xiě)高性能的Spark代碼。采用改進(jìn)建議后,如何來(lái)測(cè)試其功能及性能情況。使用Spark MLlib和Spark ML機(jī)器學(xué)習(xí)庫(kù)。Spark的流處理組件、外部的社區(qū)擴(kuò)展包。
前言
這本書(shū)為數(shù)據(jù)工程師和數(shù)據(jù)科學(xué)家所寫(xiě),他們可以從Spark 中獲得最大的收益。如果你一直在使用并深耕 Spark,但曾被內(nèi)存錯(cuò)誤和奇奇怪怪的間歇性故障所困擾,那么這本書(shū)很適合你。如果你一直在使用 Spark 進(jìn)行一些探索或者嘗試性的工作,但沒(méi)有足夠的信心將其應(yīng)用于生產(chǎn),這本書(shū)可能會(huì)有幫助。如果你對(duì) Spark 很有熱情,但是在性能提升方面沒(méi)有達(dá)到你的預(yù)期,希望這本書(shū)能有所幫助。本書(shū)的目標(biāo)人群是那些了解一些 Spark 使用方式、但對(duì) Spark或者分布式計(jì)算理解不夠的用戶。更多推薦閱讀請(qǐng)參考后面的“配套書(shū)籍及資料”。
本書(shū)旨在于幫助優(yōu)化生產(chǎn)上的重復(fù)查詢問(wèn)題,而非針對(duì)探索實(shí)驗(yàn)。與其他框架相比,使用 Spark 編寫(xiě)高性能查詢對(duì)于數(shù)據(jù)工程師來(lái)說(shuō)更加重要,這一點(diǎn)對(duì)于數(shù)據(jù)科學(xué)家更加明顯。這對(duì)于思考性能問(wèn)題時(shí)很少嚴(yán)格考慮數(shù)據(jù)的統(tǒng)計(jì)屬性、分布,以及布局的數(shù)據(jù)工程師還是很有幫助的。我們希望本書(shū)能夠幫助他們將數(shù)據(jù)管道應(yīng)用于生產(chǎn)環(huán)節(jié)之時(shí),可以更加嚴(yán)格地考慮其中的數(shù)據(jù)。希望幫助讀者提出一些問(wèn)題,比如“我的數(shù)據(jù)是如何分布的?”“是否有數(shù)據(jù)傾斜?”“這一列的值的范圍是多少”“我們期望如何對(duì)一個(gè)給定值進(jìn)行分組”,然后將這些問(wèn)題的答案應(yīng)用到編寫(xiě) Spark 查詢的邏輯中。
然而,對(duì)于數(shù)據(jù)科學(xué)家來(lái)說(shuō)即使只是出于探索性目的來(lái)使用 Spark,本書(shū)也能夠培養(yǎng)一些關(guān)于編寫(xiě)高性能 Spark 查詢的重要直觀感受,這樣隨著探索性分析規(guī)模不可避免地增長(zhǎng),你就可以在第一時(shí)間更好地運(yùn)行這些查詢。我們希望可以引導(dǎo)那些習(xí)慣以分布式視角思考數(shù)據(jù)的人,可以更加嚴(yán)格地評(píng)估自己的程序,增強(qiáng)他們?nèi)、快速的?shù)據(jù)探索能力,同時(shí)可以與幫助他們將算法應(yīng)用于生產(chǎn)的人更加有效地溝通。
無(wú)論你從事什么樣的崗位,你所使用的數(shù)據(jù)量很可能都在迅速增長(zhǎng)。你的最初方案可能需要進(jìn)行擴(kuò)展,解決新問(wèn)題時(shí)用到的老技術(shù)也可能需要更迭。我們希望這本書(shū)能幫助你利用 Apache Spark 更容易地解決新問(wèn)題,同時(shí)更高效地解決老問(wèn)題。
第一版注釋
非常感謝你正在閱讀這本書(shū)的第一版!如果你在本書(shū)中發(fā)現(xiàn)一些錯(cuò)誤、問(wèn)題,或者有思路來(lái)改進(jìn)某些方面,請(qǐng)通過(guò) high-performance-spark@googlegroups.com 聯(lián)系我們。如果你希望出現(xiàn)在本書(shū)的未來(lái)版本中的“致謝”部分,請(qǐng)備注下你要展示的名字。
配套書(shū)籍及資料
對(duì)于初學(xué) Spark 的數(shù)據(jù)科學(xué)家和開(kāi)發(fā)人員來(lái)說(shuō),由 Karau、Konwinski、Wendell 和 Zaharia 共同撰寫(xiě)的《Learning Spark》是一本不錯(cuò)的學(xué)習(xí)資料注1,另外由 Sandy Ryza、Uri Laserson、Sean Owen 和 Josh Wills 所寫(xiě)的《Advanced Analytics with Spark》對(duì)于一些數(shù)據(jù)科學(xué)家可能會(huì)比較有吸引力。而對(duì)于流處理感興趣的,即將出版的由 François Garillot 所著的《Learning Spark Streaming》可能更加適用。
書(shū)籍之外,還有一些入門級(jí)的 Spark 培訓(xùn)資料。對(duì)于喜歡視頻的來(lái)說(shuō),Paco Nathan 在 O’Reilly 有一套不錯(cuò)入門視頻。商業(yè)方面,Databricks、Cloudera以及其他的 Hadoop/Spark 供應(yīng)商也提供了相應(yīng)的 Spark 培訓(xùn)。在 Apache Spark 的文檔頁(yè)面可以找到以往的 Spark 訓(xùn)練營(yíng)錄音,以及其他非常優(yōu)秀的資源。
如果你沒(méi)有 Scala 經(jīng)驗(yàn),我們將在第 1 章中盡最大努力說(shuō)服你學(xué)會(huì) Scala。感興趣的話,可以參考 Dean Wampler 和 Alex Payne 所著的《ProgrammingScala, 2nd Edition》注2。
排版約定
本書(shū)使用了下述排版約定。
斜體(Italic)
表示新術(shù)語(yǔ)、URL、電子郵件地址、文件名和擴(kuò)展名。
等寬字體(Constant Width)
表示程序片段,以及正文中出現(xiàn)的變量、函數(shù)名、數(shù)據(jù)庫(kù)、數(shù)據(jù)類型、環(huán)境變量、語(yǔ)句和關(guān)鍵字等。
等寬斜體(constant width italic)
表示應(yīng)該由用戶輸入的值或根據(jù)上下文確定的值替換的文本。
使用示例代碼
從本書(shū)的 Github 倉(cāng)庫(kù)(https://github.com/highperformance-spark/highperformance-spark-examples)可以下載補(bǔ)充材料(代碼示例、練習(xí)等),一些測(cè)試代碼可以從 Spark Testing Base 和 Spark Validator 的 Github 倉(cāng)庫(kù)獲取。Structured Streaming 機(jī)器學(xué)習(xí)的示例,通常出現(xiàn)在“evil”分類(xi 頁(yè)的排版約定中有提及),可以從 https://github.com/holdenk/spark-structuredstreaming-ml 獲取。
本書(shū)的目的在于幫助你更好地完成工作。通常情況下,可以在你的程序或者文檔中使用本書(shū)的代碼。不必聯(lián)系我們獲取代碼的使用權(quán),除非你需要使用大量的代碼。例如,在寫(xiě)程序的時(shí)候引用幾段代碼不需要向我們申請(qǐng)?jiān)S可。但以光盤(pán)方式銷售或者重新發(fā)行 O’Reilly 書(shū)中的示例則需要獲得許可。引用本書(shū)或引用本書(shū)中的示例代碼來(lái)回答問(wèn)題也不需要申請(qǐng)?jiān)S可。代碼遵循的是Apache 2.0 協(xié)議。如果要將本書(shū)中的大量代碼加入到你的產(chǎn)品文檔,則需要申請(qǐng)?jiān)S可。
我們欣賞你在引用時(shí)注明出處,但不強(qiáng)求。引用通常包括書(shū)名、作者、出版社和 ISBN。如:“High Performance Spark by Holden Karau and Rachel Warren (O’Reilly). Copyright 2017 Holden Karau, Rachel Warren, 978-1-491-94320-5”。
如果覺(jué)得使用示例代碼的情況不屬于前面列出的合理使用或許可范圍,請(qǐng)通過(guò)電子郵件聯(lián)系我們,郵箱地址為 permissions@oreilly.com。
O’Reilly 在線學(xué)習(xí)平臺(tái)(O’Reilly Online Learning)
近40 年來(lái),O’Reilly Media 致力于提供技術(shù)和商業(yè)培訓(xùn)、知識(shí)和卓越見(jiàn)解,來(lái)幫助眾多公司取得成功。
我們擁有獨(dú)一無(wú)二的專家和革新者組成的龐大網(wǎng)絡(luò),他們通過(guò)圖書(shū)、文章、會(huì)議和我們的在線學(xué)習(xí)平臺(tái)分享他們的知識(shí)和經(jīng)驗(yàn)。O’Reilly 的在線學(xué)習(xí)平臺(tái)允許你按需訪問(wèn)現(xiàn)場(chǎng)培訓(xùn)課程、深入的學(xué)習(xí)路徑、交互式編程環(huán)境,以及O’Reilly 和200 多家其他出版商提供的大量文本和視頻資源。有關(guān)的更多信息,請(qǐng)?jiān)L問(wèn)http://oreilly.com。
如何聯(lián)系作者
如果有需要進(jìn)行反饋的內(nèi)容, 請(qǐng)發(fā)郵件至 high-performance-spark@googlegroups.com。如果你有任何關(guān)于Spark 的任何想法,請(qǐng)?jiān)?twitter 上關(guān)注我們:
Holden: http://twitter.com/holdenkarau。
Rachel: https://twitter.com/warre_n_peace。
聯(lián)系我們
美國(guó):
O’Reilly Media, Inc.
1005 Gravenstein Highway North
Sebastopol, CA 95472
中國(guó):
北京市西城區(qū)西直門南大街2號(hào)成銘大廈C座807室(100035)
奧萊利技術(shù)咨詢(北京)有限公司
如果你對(duì)本書(shū)有一些評(píng)論或技術(shù)上的建議,請(qǐng)發(fā)送電子郵件到bookquestions@oreilly.com。
有關(guān)其他圖書(shū)、講座、會(huì)議、新聞的信息,請(qǐng)?jiān)L問(wèn)我們的網(wǎng)站:http://www.oreilly.com。
我們的Facebook:http://facebook.com/oreilly。
我們的Twitter:http://twitter.com/oreillymedia。
我們的YouTube:http://www.youtube.com/oreillymedia。
致謝
作者要感謝每一個(gè)曾對(duì)我們的早期文稿提出意見(jiàn)和建議的人。特別感謝 Anya Bida、Jakob Odersky 和 Katharine Kearnan 審核文稿和圖表。我們要感謝Mahmoud Hanafy 對(duì)示例代碼以及早期文稿的審核和改進(jìn)。我們還要感謝Michael Armbrust 對(duì) SQL 章節(jié)文稿的審核及反饋。Justin Pihony 是最活躍的早期讀者之一,他提出了各個(gè)方面(包括語(yǔ)言、格式等)的修改建議。
感謝我們 O’Reilly 早期發(fā)行時(shí)的所有讀者,他們對(duì)于各種錯(cuò)誤提出了不少反饋,其中包括 Kanak Kshetri 和 Rubén Berengue。
最后,感謝我們各自的雇主理解我們?cè)谶@本書(shū)的工作。尤其是Lawrence Spracklen 堅(jiān)持讓我們?cè)谶@里提到他。
Holden Karau是一位加拿大人,在IBM的Spark技術(shù)中心擔(dān)任軟件開(kāi)發(fā)工程師。同時(shí)作為一位Spark committer,經(jīng)常在PySpark和機(jī)器學(xué)習(xí)方面進(jìn)行貢獻(xiàn)。另外曾在多次國(guó)際會(huì)議中發(fā)表關(guān)于Spark的演講。
Rachel Warren是Alpine Data的軟件工程師和數(shù)據(jù)科學(xué)家。在工作中,她利用Spark來(lái)解決實(shí)際場(chǎng)景中的數(shù)據(jù)處理和機(jī)器學(xué)習(xí)問(wèn)題。另外,她還曾在工業(yè)界以及學(xué)術(shù)界擔(dān)任過(guò)分析師和導(dǎo)師。
目錄
前言 .1
第1 章 高性能Spark 介紹 7
1.1 Spark 是什么以及性能的重要性 .7
1.2 你可以從本書(shū)中得到什么 8
1.3 Spark 版本 .9
1.4 為什么是 Scala ? 9
1.4.1 成為一名 Spark 專家必須要學(xué)習(xí)一點(diǎn) Scala .9
1.4.2 Spark 的 Scala API 比 Java API 更好用 10
1.4.3 Scala 比 Python 更高效 10
1.4.4 為什么不用 Scala ? 11
1.4.5 學(xué)習(xí) Scala 11
1.5 小結(jié) 12
第2 章 Spark 運(yùn)行原理 .13
2.1 Spark 如何融入大數(shù)據(jù)生態(tài)系統(tǒng) 14
2.2 Spark 并行計(jì)算模型:RDD 16
2.2.1 惰性求值 17
2.2.2 內(nèi)存持久化和內(nèi)存管理 20
2.2.3 不可變性和 RDD 接口 . 21
2.2.4 RDD 的類型 23
2.2.5 RDD 上的函數(shù):轉(zhuǎn)換與行動(dòng) 24
2.2.6 寬依賴和窄依賴 25
2.3 Spark 作業(yè)調(diào)度 . 27
2.3.1 應(yīng)用程序間的資源分配 27
2.3.2 Spark 應(yīng)用程序 . 28
2.4 Spark Job 剖析 29
2.4.1 有向無(wú)環(huán)圖(DAG) 30
2.4.2 作業(yè)(Job) 31
2.4.3 階段(Stage) 31
2.4.4 任務(wù)(Task) 32
2.5 小結(jié) 34
第 3 章 DataFrame、Dataset 和Spark SQL 35
3.1 從 SparkSession(或者 HiveContext 和 SQLContext)入門 . 36
3.2 Spark SQL 依賴 39
3.2.1 管理 Spark 依賴 39
3.2.2 避免使用 Hive JAR 40
3.3 schema 基礎(chǔ) 41
3.4 DataFrame API 45
3.4.1 轉(zhuǎn)換 45
3.4.2 基于多個(gè) DataFrame 的轉(zhuǎn)換 . 56
3.4.3 普通的 SQL 查詢以及與 Hive 數(shù)據(jù)交互 . 57
3.5 DataFrame 和 Dataset 中的數(shù)據(jù)表示 . 58
3.6 數(shù)據(jù)加載和保存函數(shù) . 59
3.6.1 DataFrameWriter 和 DataFrameReader . 60
3.6.2 格式 60
3.6.3 保存模式 70
3.6.4 分區(qū)(發(fā)現(xiàn)和寫(xiě)入) . 70
3.7 Dataset 71
3.7.1 與 RDD、DataFrame 和本地集合的互操作性 72
3.7.2 編譯時(shí)強(qiáng)類型 73
3.7.3 簡(jiǎn)易函數(shù)式轉(zhuǎn)換操作(類似 RDD) . 74
3.7.4 關(guān)系型轉(zhuǎn)換操作 74
3.7.5 多 Dataset 關(guān)系轉(zhuǎn)換操作 . 75
3.7.6 Dataset 的分組操作 75
3.8 使用用戶自定義的函數(shù)和聚合函數(shù)(UDF、UDAF)進(jìn)行擴(kuò)展 . 76
3.9 查詢優(yōu)化器 . 79
3.9.1 邏輯和物理計(jì)劃 79
3.9.2 代碼生成 79
3.9.3 大型查詢計(jì)劃和迭代算法 80
3.10 調(diào)試 Spark SQL 查詢 80
3.11 JDBC/ODBC 服務(wù)器 81
3.12 小結(jié) . 82
第 4 章 Join (SQL 和Spark Core) 84
4.1 Spark Core 中的 Join . 84
4.1.1 選擇 Join 類型 86
4.1.2 選擇執(zhí)行計(jì)劃 88
4.2 Spark SQL 中的 Join 91
4.2.1 DataFrame 的 Join 91
4.2.2 Dataset 的 Join 95
4.3 小結(jié) 96
第 5 章 高效的轉(zhuǎn)換 .97
5.1 窄轉(zhuǎn)換與寬轉(zhuǎn)換 98
5.1.1 對(duì)于性能的影響 100
5.1.2 對(duì)于容錯(cuò)的影響 101
5.1.3 coalesce 的特殊情況 102
5.2 轉(zhuǎn)換會(huì)返回什么類型的 RDD . 102
5.3 最小化對(duì)象創(chuàng)建成本 104
5.3.1 重用現(xiàn)有對(duì)象 . 104
5.3.2 使用更小的數(shù)據(jù)結(jié)構(gòu) 108
5.4 mapPartitions 迭代器到迭代器的轉(zhuǎn)換 111
5.4.1 什么是迭代器到迭代器的轉(zhuǎn)換? 112
5.4.2 空間和時(shí)間優(yōu)勢(shì) 113
5.4.3 案例 . 114
5.5 集合操作 117
5.6 降低初始化開(kāi)銷 118
5.6.1 共享變量 119
5.6.2 廣播變量 119
5.6.3 累加器 121
5.7 重用 RDD . 125
5.7.1 重用的案例 126
5.7.2 判斷重新計(jì)算是否足夠劃算 129
5.7.3 重用類型:緩存、持久化、檢查點(diǎn)、shuffle 文件 130
5.7.4 Alluxio(之前的 Tachyon) 135
5.7.5 LRU 緩存 . 135
5.7.6 繁忙集群的注意事項(xiàng) 137
5.7.7 與累加器交互 . 138
5.8 小結(jié) . 139
第 6 章 處理鍵值對(duì)數(shù)據(jù) . 140
6.1 金發(fā)女孩案例 . 142
6.1.1 金發(fā)女孩之版本 0:迭代方案 143
6.1.2 如何使用 PairRDDFunctions 和 OrderedRDDFunctions 146
6.2 鍵值對(duì)上的行動(dòng)操作 147
6.3 groupByKey 函數(shù)有什么風(fēng)險(xiǎn) . 148
6.3.1 金發(fā)女孩之版本 1:groupByKey 方案 148
6.3.2 為什么 groupByKey 會(huì)失敗 150
6.4 選擇聚合操作 . 152
6.5 涉及多個(gè) RDD 的操作 156
6.6 分區(qū)器和鍵值對(duì)數(shù)據(jù) 157
6.6.1 使用 Spark 的分區(qū)器對(duì)象 . 158
6.6.2 哈希分區(qū) 158
6.6.3 范圍分區(qū) 159
6.6.4 自定義分區(qū) 160
6.6.5 保留跨不同轉(zhuǎn)換的分區(qū)信息 160
6.6.6 利用協(xié)同位置(Co-located)和協(xié)同分區(qū)(Co-Partitioned)
的 RDD 161
6.6.7 PairRDDFunctions 中關(guān)于映射和分區(qū)函數(shù)的字典 163
6.7 OrderedRDDFunctions 字典 165
6.8 二級(jí)排序和 repartitionAndSortWithinPartitions 167
6.8.1 在按鍵分組和按值排序的函數(shù)中利用
repartitionAndSortWithinPartitions 168
6.8.2 如何不按照兩個(gè)排序鍵排序 172
6.8.3 金發(fā)女孩之版本 2:二級(jí)排序 172
6.8.4 金發(fā)女孩問(wèn)題的另外一種不同解法 . 176
6.8.5 金發(fā)女孩之版本 3:對(duì)單元格值排序 . 181
6.9 掉隊(duì)檢測(cè)與不均衡數(shù)據(jù) . 182
6.9.1 再次回到金發(fā)女孩問(wèn)題 . 184
6.9.2 金發(fā)女孩之版本 4:在每個(gè)分區(qū)上歸并為不同值 184
6.10 小結(jié) 191
第 7 章 Scala 之外 192
7.1 JVM 之內(nèi)、Scala 之外 194
7.2 Scala 之外、JVM 之外 198
7.2.1 PySpark 工作原理 . 198
7.2.2 SparkR 工作原理 207
7.2.3 Spark.jl(Julia Spark) 209
7.2.4 Eclair JS 工作原理 210
7.2.5 Spark 基于公共語(yǔ)言運(yùn)行時(shí)(CLR),C# 及類似語(yǔ)言 211
7.3 在 Spark 中調(diào)用其他語(yǔ)言 . 211
7.3.1 使用管道及類似工具 211
7.3.2 JNI 213
7.3.3 Java 本地訪問(wèn)(JNA) . 216
7.3.4 一切的背后都是 FORTRAN 217
7.3.5 談?wù)?GPU . 218
7.4 未來(lái) . 219
7.5 小結(jié) . 219
第 8 章 測(cè)試和驗(yàn)證 221
8.1 單元測(cè)試 221
8.1.1 一般 Spark 單元測(cè)試 222
8.1.2 模擬 RDD . 227
8.2 獲取測(cè)試數(shù)據(jù) . 228
8.2.1 生成大數(shù)據(jù)集 . 229
8.2.2 抽樣 . 230
8.3 用 ScalaCheck 檢查屬性 232
8.4 集成測(cè)試 235
8.5 性能驗(yàn)證 237
8.5.1 用于性能驗(yàn)證的 Spark 計(jì)數(shù)器 237
8.5.2 性能驗(yàn)證相關(guān)項(xiàng)目 238
8.6 作業(yè)驗(yàn)證 239
8.7 小結(jié) . 240
第 9 章 Spark MLlib 和ML 241
9.1 在 Spark MLlib 和 Spark ML 之間選擇 . 241
9.2 使用 MLlib 242
9.2.1 MLlib 入門(組織和導(dǎo)入) 242
9.2.2 MLlib 特征編碼和數(shù)據(jù)準(zhǔn)備 244
9.2.3 特征縮放和選擇 248
9.2.4 MLlib 模型訓(xùn)練 . 249
9.2.5 預(yù)測(cè) . 250
9.2.6 服務(wù)和持久化 . 251
9.2.7 模型評(píng)估 254
9.3 使用 Spark ML 254
9.3.1 Spark ML 組織和導(dǎo)入 254
9.3.2 管道階段 256
9.3.3 參數(shù)解釋 257
9.3.4 數(shù)據(jù)編碼 258
9.3.5 數(shù)據(jù)清洗 261
9.3.6 Spark ML 模型 261
9.3.7 整合成管道 262
9.3.8 訓(xùn)練管道 263
9.3.9 訪問(wèn)單個(gè)階段 . 264
9.3.10 數(shù)據(jù)持久化和 Spark ML . 264
9.3.11 使用自定義算法擴(kuò)展 Spark ML 管道 267
9.3.12 模型和管道持久化與 Spark ML 服務(wù) 275
9.4 一般服務(wù)考量因素 276
9.5 小結(jié) . 276
第 10 章 Spark 組件和包 278
10.1 基于 Spark 的流處理 280
10.1.1 Source 和 Sink . 281
10.1.2 批處理間隔 283
10.1.3 數(shù)據(jù) checkpoint 間隔 284
10.1.4 DStream 的注意事項(xiàng) 284
10.1.5 Structured Streaming 的考量因素 286
10.1.6 高可用性模式(或處理 Driver 程序故障或進(jìn)行 checkpoint) 294
10.2 GraphX 295
10.3 使用社區(qū)包和庫(kù) 295
10.4 小結(jié) 298
附錄 調(diào)優(yōu)、調(diào)試以及開(kāi)發(fā)者容易忽略的其他問(wèn)題 301