2017-07-28 191 views
-1

我正在嘗試使用數據源MySQL的Apache Spark。我有一個集羣有1個主節點和1個從屬節點,都有8 GB RAM和2個核心我正在提交我的SQL查詢以使用spark-shell進行激發,並且該表有這麼多行。我正在執行到該表上。和時間由MySQL是5.2secs和使用火花時,我正在執行查詢時間是21Secs。爲什麼發生這種情況?爲什麼spark還比mysql慢?

我還設置了一些配置,如partitionColumn,upperBound,lowerBound和numofPartitions但仍然沒有變化。

我也曾嘗試與執行使用1,2,4內核的查詢,但在火花所花費的時間是相同的21Secs

發生這個問題是因爲我的MySQL數據庫在單臺機器上,而所有的火花節點都試圖將數據查詢到單臺機器上?

任何人都可以幫我解決這個問題嗎?

有一個名爲demo_call_stats上我試圖查詢表的數據庫是:

val jdbcDF = spark.read.format("jdbc").options(Map("url" -> "jdbc:mysql://192.168.0.31:3306/cmanalytics?user=root&password=","zeroDateTimeBehaviour"->"convertToNull", "dbtable" -> "cmanalytics.demo_call_stats", "fetchSize" -> "10000", "partitionColumn" -> "newpartition", "lowerBound" -> "0", "upperBound" -> "4", "numPartitions" -> "4")).load() 

jdbcDF.createOrReplaceTempView("call_stats") 

val sqlDF = sql("select Count(*), classification_id from call_stats where campaign_id = 77 group by classification_id") 

sqlDF.show() 

任何幫助將非常感激。

感謝

+1

如果數據不在RAM中,Spark在執行計算之前需要將其拉出。因此,網絡IO可能是一個瓶頸。由於我不確定你是如何衡量你的查詢性能的,也不知道你的查詢是什麼,也不知道你的數據分佈,所以我們在這裏幫不了你的忙。 – eliasah

+0

考慮共享一些代碼和一些關於你的數據的信息!你可能沒有得到一個具體的解決方案,但也許我可以幫助你一些指針。 – eliasah

+0

@eliasah我正在測量使用火花Web UI的查詢性能。 –

回答

5

有幾件事情你應該明白這裏:

儘管你可能已經聽說過,Spark是不是「比MySQL快」,僅僅是因爲這種一般性的不意味着什麼。 對於某些查詢,Spark比MySQL更快,MySQL對於其他人來說比Spark快。 一般來說,MySQL是一個關係數據庫,這意味着它已被設想爲 作爲應用程序的後端。只要對索引進行索引,它就可以高效地訪問記錄。

在考慮數據庫時,我喜歡把它們想象成一個圖書館,有一個圖書管理員來幫助你獲得你想要的圖書 (我在這裏講一個非常古老的學校圖書館,沒有任何計算機來幫助圖書管理員) 。

如果你問你的圖書館員: 「我想知道你多少書是關於地緣政治」, 館員可以到地緣政治貨架和計數的那個書架上圖書的數量。

如果你問你的圖書館員: 「我想知道你多少書有至少有500頁的」, 圖書管理員將不得不看每一個在圖書館看書回答您的查詢。 在SQL中,這稱爲全表掃描。 當然,您可以讓一些圖書管理員(處理器)在查詢上工作得更快, ,但您的圖書館(計算機)中不能超過其中的一部分(我們假設多達16個)。

現在,Spark已被設計爲處理大量數據,即如此大的圖書館 以至於它們不適合單個建築物,並且即使這樣,它們也會如此之多以至於甚至可以達到16個圖書館員需要幾天時間才能回答你的第二個問題。

讓Spark比MySQL更快的原因是:如果你把你的書放在幾棟建築物中,你可以有16個館員每棟工作你的答案。 你也可以處理更多的書籍。

此外,由於星火主要是回答第二類查詢,而不是像這樣的查詢「請帶上我'肖像灰色',由奧斯卡王爾德」,這意味着Spark不關心,至少默認情況下,以任何特定的方式分類您的書籍。 這意味着如果你想用火花找到那本特定的書,你的圖書館員將有 通過整個圖書館來找到它。

當然,Spark使用許多其他類型的優化來更有效地執行某些查詢,但索引不是其中之一。 (如果您熟悉mySQL中的主鍵的概念,則Spark中沒有這樣的東西) 其他優化包括像Parquet和ORC這樣的存儲格式,它允許您只讀取有用的列 以回答您的查詢,並且壓縮(例如Snappy),它們旨在增加圖書館的數量,您可以在圖書館中放入 而無需推牆。

我希望這個比喻對你有所幫助,但請記住,這只是一個比喻,並且 完全不符合現實。

現在,要回你的問題的具體細節:

假設campaign_id是你的主鍵或您在此列創建的索引,MySQL將只 來讀取其中campaign_id = 77行。另一方面,Spark將不得不要求mySQL將該表中的所有行發送到Spark。 如果Spark很聰明,它只會詢問campaign_id = 77,並且可能會向mySQL發送多個查詢以並行獲取範圍。 但是這意味着MySQL只能讀取和聚合的所有數據都將被序列化,發送到Spark,並由Spark進行聚合。 我希望你明白爲什麼這會花更長的時間。

如果您希望Spark比MySQL更快地回答您的查詢,您應該嘗試以另一種格式複製表格。

// replace this line : 
// jdbcDF.createOrReplaceTempView("call_stats") 
// with : 
jdbcDF.write.format("orc").saveAsTable("call_stats") 

另一件事你可以嘗試是緩存數據是這樣的:

jdbcDF.cache().createOrReplaceTempView("call_stats") 

緩存不會帶來任何改善的第一個查詢的同時執行它,它會緩存數據,但如果你繼續質疑同樣的觀點,它可能會更快。但是正如我上面所解釋的,這並不意味着Spark對於任何事情都會比mySQL更快。

對於小數據和本地部署,您還可以通過更改此配置 參數spark.sql.shuffle.partitions=4(默認爲200)來獲得perf改進。

希望這會有所幫助。