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