spark官方文档_这些未在 Spark SQL 文档中说明的优化措施,你知道吗?
本文來自上周(2020-11-17至2020-11-19)舉辦的?Data + AI Summit 2020?(原 Spark+AI Summit),主題為《Spark SQL Beyond Official Documentation》的分享,作者 David Vrba,是 Socialbakers 的高級機器學習工程師。
實現(xiàn)高效的 Spark 應用程序并獲得最大的性能為目標,通常需要官方文檔之外的知識。理解 Spark 的內部流程和特性有助于根據(jù)內部優(yōu)化設計查詢,從而在執(zhí)行期間實現(xiàn)高效率。在這次演講中,我們將重點討論 Spark SQL 的一些官方文檔中沒有很好描述的內部特性,重點在一些基本示例上解釋這些特性,同時分享一些性能技巧。
下面是本次分享的超清視頻:
本次分享主要有兩大主題:
?Spark SQL 中的統(tǒng)計信息(Statistics)?以排序的方式將數(shù)據(jù)存儲在文件中
Spark SQL 中的統(tǒng)計信息(Statistics)
統(tǒng)計信息這塊的分享主要包括以下四個方面:
?我們怎么可以看到統(tǒng)計信息?統(tǒng)計信息是如何計算的?統(tǒng)計信息是怎么使用?有什么注意事項?
在 Spark 中,我們可以通過以上方法來查看表級別的統(tǒng)計信息、,輸出的信息里面有個 Statistics 那行,那就是本次分享要提到的統(tǒng)計信息。
如果想查看列級別的統(tǒng)計信息,可以使用 DESCRIBE EXTENDED table_name column_name 進行查看。輸出的信息可以看到這列的最大最小值、null 的數(shù)量、去重之后的值數(shù)量等信息。
如果我們使用的是 Apache Spark 3,我們還可以通過 explain(mode="cost") 來查看統(tǒng)計信息:統(tǒng)計信息是通過執(zhí)行計劃樹的葉子節(jié)點計算的,然后從樹的最底層往上傳遞,同時 Spark 也會利用這些統(tǒng)計信息來修改執(zhí)行樹的執(zhí)行過程。統(tǒng)計信息的傳遞主要有兩種方法:最簡單的方法(Simple way)以及高級方法。上面就是統(tǒng)計信息的最簡單的傳遞方法,這種方法只傳遞 sizeInBytes。從右上圖可以看出,我們通過 user_id?0 的過濾條件來過濾數(shù)據(jù),其實表中肯定沒有用戶的 user_id 小于 0 ,但是我們可以通過邏輯計劃看出,簡單的統(tǒng)計信息傳遞,Filter 節(jié)點的統(tǒng)計信息的?sizeInBytes 和 Relation 節(jié)點是一樣。高級傳遞方式的特點是可以傳遞?sizeInBytes 信息、行數(shù)以及列級別的信息。這種傳遞方式必須使用 Apache Spark 2.2 版本,而且需要打開 CBO(默認沒有打開,需要配置 spark.sql.cbo.enabled=true)。上面例子可以看出,統(tǒng)計信息里面只有?sizeInBytes 和 rowCount,并沒有列級別的統(tǒng)計信息,特別是 user_id 這列的統(tǒng)計信息。所以 Filter 節(jié)點和 Relation 節(jié)點的統(tǒng)計信息是一樣的,因為 Spark 無法利用這些統(tǒng)計信息算出文件里面到底有多少滿足 user_id如果我們算出 user_id 的統(tǒng)計信息,可以看出,Filter 利用了這些統(tǒng)計信息,算出過濾后的數(shù)據(jù)行數(shù)為0。
那么,上面提到的統(tǒng)計信息是如何計算的呢?在 Spark 中主要有三種:
?從 metastore 中獲取
?利用 Hadoop API 計算,僅僅計算 sizeInBytes?使用 sizeInBytes 的默認值,通過 spark.sql.defaultSizeInBytes 配置,默認為 Long 的最大值。
上面是計算流程,圖中的每個節(jié)點是條件,根據(jù)不同條件選擇不同的路徑。
在 Spark 中,統(tǒng)計信息主要在兩種情況使用:
?Join 策略選擇?多表 Join,調節(jié) Join 表的順序,這個需要打開 spark.sql.cbo.joinReorder.enable。
以上就是 Spark 統(tǒng)計信息相關的知識點。以排序的方式將數(shù)據(jù)存儲在文件中
以排序的方式將數(shù)據(jù)存儲到文件主要涉及排序的函數(shù)有哪些,怎么將數(shù)據(jù)以排序的形式存儲在文件。
上面就是 Spark 中排序的算子:
?orderBy/sort?這個是 DataFrame 的轉換算子,其是在不同的作業(yè)粒度對數(shù)據(jù)進行排序,需要 shuffle 來達到全局的有序;
?sortWithinPartitions?這個也是 DataFrame 的轉換算子,是分區(qū)粒度的排序;?sortBy?這個通常是在 DataFrameWriter 上調用,并且在 write 算子調用之后調用的,一般和 bucketing 算子一起使用,需要配合使用 saveAsTable
為了有個直觀的體驗,我們用個例子來介紹。在這個例子中,我們使用 year 這列對數(shù)據(jù)進行分區(qū);每個分區(qū)使用 user_id 來進行排序;每個分區(qū)只有一個文件,這個文件是通過 user_id 進行排序的。
很多人會很輕松的寫出以上的程序。但是遺憾的是,最后保存在文件系統(tǒng)的文件并沒有排序。如果需要保存的數(shù)據(jù)是有序的,需要保證 partitionColumns 有序, bucketingIdExpression 有序以及 sortColumns 有序的順序。如果這個沒有滿足,則 Spark 將忽略之前的排序。
上面例子中因為我們對 year 這列進行分區(qū),但是使用 user_id 進行排序,所以最后保存的文件肯定不會有序。
如果我們將?sortWithinPartitions('user_id') 修改為?sortWithinPartitions('year', 'user_id') 。這樣最后算出的文件就是分區(qū)內有序的。
到這里我們已經(jīng)學習了如何使用統(tǒng)計信息來提升我們的 Join 性能,以及如何以有序的方式來存儲數(shù)據(jù)。
好了,今天的分享就到這里,歡迎大家轉發(fā)+點贊。
Java與大數(shù)據(jù)架構
7年老碼農(nóng),10W+關注者。【Java與大數(shù)據(jù)架構】全面分享Java編程、Spark、Flink、Kafka、Elasticsearch、數(shù)據(jù)湖等干貨。歡迎掃碼關注!
總結
以上是生活随笔為你收集整理的spark官方文档_这些未在 Spark SQL 文档中说明的优化措施,你知道吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中产生随机数模块_Pytho
- 下一篇: oracle数据库如何写翻页_oracl