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