我一直對關聯式資料庫有很好的接觸,後來又接觸了像 Spark 這樣的分散式系統。最初,我深入研究了 DBMS,既設定複雜的查詢、管理,也主要是如何為 DBMS 組合一個執行腳本。當我開始更多地使用Spark,後來又使用Databricks 時,最初我在必須建立的場景中沒有遇到效能問題,但隨著大數據領域真正成為大數據,我開始在例程中遇到效能問題,每個例程都會增加30%一周,這讓我尋找Spark 如何「在幕後」工作,主要是因為我已經知道DBMS 是如何運作的,這幫助我了解我將在這裡帶來的一些概念。
讓我們保持簡短,因為我希望本文專注於效能分析場景、技術和最佳實踐。
此元件是Spark的基礎,它負責記憶體管理、任務、故障復原、I/O管理,換句話說,它操作RDD。因此,他是一個擁有很大一部分集群的傢伙。
這個元件是spark生態系(叢集)真正的worker,它是接收寫入或讀取指令(任務)的元件,可以在磁碟上,也可以在記憶體上,也可以在兩者上(稍後我會解釋為什麼會出現這種情況)播放)。
Workers 對於已經熟悉分散式運算的人來說就是字面上的意思,它們是叢集的節點,所以它是我上面提到的執行器的“託管”,每個工作器可以包含一個或多個執行器。它負責管理分配給執行者的資源,就好像執行者是助手,工人是倉庫工人一樣。如果他是他報告的倉庫管理員怎麼辦?
這是經理,他為工作人員管理資源(內存和CPU),他決定每個應用程式將有多少執行者以及將分配多少資源,他管理他的''發送的任務boss',我將在下面進一步解釋,由於它的職責更高,它還監視叢集的狀態以從故障中恢復,並根據需要重新分配任務。 (注意:叢集管理器有多種類型:Yarn、mesos、kubernetes 以及最簡單的獨立叢集管理器)。
嗯,這是老闆或網關,我說網關是因為任何Spark 應用程式都會經過它,它是允許應用程式與叢集互動的東西,即工作人員和執行者,它允許和管理工作人員之間的任務,透過這種方式,它在配置、執行器數量和記憶體等資源方面管理整個應用程式。您需要知道任務是如何執行的嗎?在這裡與這位老闆交談。
所以,以一種說明性的方式:
當我與關係銀行方面合作時,出現效能問題,主要是在應用程式中的流程或函數或查詢中,我分析了以下幾個方面:
嗯,我想就是這樣,現在這些點與 Apache Spark 有什麼共同點?
總結每一個是什麼,儘管有名字,你已經可以得到一個想法:
邏輯計畫:
將原始查詢表示為一系列邏輯運算。它是查詢的抽象形式,而不考慮它的實際執行方式。包括有關將要執行的操作的信息,例如過濾、選擇、連接、聚合以及錯誤的“小事情”,哈哈。
物理平面:
詳細說明 Spark 將如何實際執行查詢。這包括操作順序以及將使用哪些演算法(例如 DBMS 演算法)。它可能包括有關資料如何在執行器之間分區和分配的詳細資訊。
執行策略:
物理平面可以顯示 Spark 可以使用的不同執行策略,例如“Broadcast Join”或“Shuffle Hash Join”,這取決於操作和資料大小。我也會解釋一下執行計劃的主要演算法,冷靜一下...
預計費用:
儘管並非總是顯示,但某些計劃可能包括計劃不同部分的成本估算,以幫助您了解處理的哪一部分可能成本最高。
我們有一個文字形式的「根」形式,使用explain()命令,它將有一個類似於下面的輸出,顯示一個簡單的過濾器和一個資料框:
== 實體計畫==
*(2) 過濾器(值 > 1)
- *(2) 項目 [名稱#0,值#1]
- *(1) 掃描現有RDD[名稱#0, 值#1]
客觀地,我們可以透過介面、透過 Spark UI 來分析它,在 Databricks 中我們可以存取它,無論是在單元執行中、在作業中或在叢集中。在 Apache Spark 中,它直接是預設連接埠 4040 上的 IP。
Spark UI 分為幾個有用的部分:
作業:顯示應用程式中執行的所有作業的清單。每個作業對應於程式碼中的一個操作。
階段:顯示組成每個作業的階段。階段是可以並行執行的工作細分。
任務:詳細說明每個階段內的各個任務,包括有關任務執行時間和狀態的資訊。
儲存:提供有關 RDD(彈性分散式資料集)的記憶體和儲存使用情況的資訊。
環境:顯示運行時環境屬性,包括 Spark 配置和系統變數。
Executors:顯示為應用程式建立的執行器的信息,包括記憶體使用情況、磁碟使用情況和效能統計資料。
在這裡我是有等級制度的,好嗎?這就是事情發生的順序。
我想要將圖像放在螢幕上! !
首先,我將解釋 Spark UI 介面和執行計劃中演示的主要演算法,無論是邏輯計劃還是物理計劃:
注意:記住這裡的資料集與 Spark 表相同;)
1。讓我們從最著名的掃描開始:
2。加入(這個給了一些B.O):
Broadcast Hash Join:當其中一個資料集夠小,可以傳輸到叢集中的所有節點時使用,避免Shuffle(我會詳細解釋這個東西,但簡而言之,這是一種數據shuffle 操作最終加入)。
隨機雜湊連接:兩個資料集(如果您願意,也可以是表格)都會隨機排列,以便對應的鍵位於同一分區中。當資料集很大,無法傳輸到其他節點時使用。
排序合併連接:要求在連接之前對兩個資料集進行排序。對於已經分區和排序的大型資料集來說它是有效的,也就是說,連接是透過分區和排序的列完成的(例如df.write.partitionBy("coluna1").sortBy("coluna2"). parquet("路徑/到/儲存/分區")
3。聚合(總和、計數、分組等...):
HashAggregate:使用雜湊表來聚合資料。它對於適合記憶體的大型資料集非常有效。
排序聚合。對資料進行排序後進行聚合。當資料無法放入記憶體時使用。
4。隨機播放(小心這傢伙):
5。交換:
6。項目:
7。篩選:
8。排序:
上面的所有這些演算法都可以像我之前所說的透過explain()指令來觀察。
1。 Join 和 GroupBy 操作
join() 和 groupByKey() 等操作通常會觸發 shuffle,從而在分區之間重新分配資料。這可能會導致:
高磁碟 I/O 使用率:Shuffle 會產生許多中間文件,這會使執行器的本機磁碟飽和。
高網路負載:執行器之間傳輸的資料量可能很大,取決於所需的連線數量(映射器數量乘以減速器數量)
緩解
在 Spark UI 中隨機排列指標:
shuffle 的工作原理以及成本高昂的原因:
由於 Databricks、Jupyter Notebook 和 Google Colab 的廣泛流行,絕大多數人都使用 Notebook 進行工作。因此,將每個查詢或轉換劃分為單獨的單元格,這樣可以更輕鬆地識別哪個部分是效能問題。把一切放在一起,有好幾個工作,很難知道是哪個階段。
使用合併而不是覆蓋,我知道這需要更多工作,但它更具邏輯性和執行力,因為合併將使用比在資料湖中再次「轉儲」覆蓋整個表更少的I/O。
使用cache()或persist()將中間資料儲存在記憶體中,特別是當它將在多個操作中重複使用時。這可以減少重新計算時間並提高效能。
如果你不知道,Spark 運行在JVM 上,因此它本身就是Java,當你使用Python 創建著名的UDF - 用戶定義函數時,你為Spark 留下了一種“黑匣子”,阻止了它自動優化。只要有可能,請使用針對效能進行最佳化的內建 Spark SQL 函數。
嗯,我想我已經寫下了我想到的一切,我喜歡寫文章,因為它可以幫助我記住一些場景。我打算錄製一個影片來展示這一切,在實踐中使用一些公開數據,我可能會在Kaggle 上獲取它,所以在LinkedIn 上關注我,以了解與數據、人工智慧和軟體開發世界相關的一切
--> https://www.linkedin.com/in/airton-lira-junior-6b81a661
在 LinkedIn 上追蹤我,給我動力,我喜歡回饋,我也完全願意改善知識分享。
如果您已經讀到這裡,恭喜您! ! !我希望它能克服所有效能問題。在下一篇文章中,我將介紹 Databricks 的優勢,請在 LinkedIn 上關注我以了解詳情。謝謝! !
以上是了解並應用 Apache Spark 調優策略的詳細內容。更多資訊請關注PHP中文網其他相關文章!