Spark SQL 和 Shark 在架構上有哪些區別?將來會合併嗎?

在DataBricks看到最新的blog(Spark SQL: Manipulating Structured Data Using Spark)介紹Spark SQL Alpha即將在Spark1.0中發布,也提到了Shark會逐漸採用Spark SQL作為查詢優化器等,想知道就目前而言技術架構上二者的區別


Shark為了實現Hive兼容,在HQL方面重用了Hive中HQL的解析、邏輯執行計劃翻譯、執行計劃優化等邏輯,可以近似認為僅將物理執行計劃從MR作業替換成了Spark作業(輔以內存列式存儲等各種和Hive關係不大的優化);同時還依賴Hive Metastore和Hive SerDe(用於兼容現有的各種Hive存儲格式)。這一策略導致了兩個問題,第一是執行計劃優化完全依賴於Hive,不方便添加新的優化策略;二是因為MR是進程級並行,寫代碼的時候不是很注意線程安全問題,導致Shark不得不使用另外一套獨立維護的打了補丁的Hive源碼分支(至於為何相關修改沒有合併到Hive主線,我也不太清楚)。

Spark SQL解決了這兩個問題。第一,Spark SQL在Hive兼容層面僅依賴HQL parser、Hive Metastore和Hive SerDe。也就是說,從HQL被解析成抽象語法樹(AST)起,就全部由Spark SQL接管了。執行計劃生成和優化都由Catalyst負責。藉助Scala的模式匹配等函數式語言特性,利用Catalyst開發執行計劃優化策略比Hive要簡潔得多。去年Spark summit上Catalyst的作者Michael Armbrust對Catalyst做了一個簡要介紹:2013 | Spark Summit(知乎竟然不能自定義鏈接的文字?)。第二,相對於Shark,由於進一步削減了對Hive的依賴,Spark SQL不再需要自行維護打了patch的Hive分支。Shark後續將全面採用Spark SQL作為引擎,不僅僅是查詢優化方面。

此外,除了兼容HQL、加速現有Hive數據的查詢分析以外,Spark SQL還支持直接對原生RDD對象進行關係查詢。同時,除了HQL以外,Spark SQL還內建了一個精簡的SQL parser,以及一套Scala DSL。也就是說,如果只是使用Spark SQL內建的SQL方言或Scala DSL對原生RDD對象進行關係查詢,用戶在開發Spark應用時完全不需要依賴Hive的任何東西。

能夠對原生RDD對象進行關係查詢,個人認為大大降低了用戶門檻。一方面當然是因為熟悉SQL的人比熟悉Spark API的人多,另一方面是因為Spark SQL之下有Catalyst驅動的查詢計劃優化引擎。雖然在很多方面Spark的性能完爆Hadoop MapReduce好幾條街,但Spark的運行時模型也比MapReduce複雜不少,使得Spark應用的性能調優比較tricky。雖然從代碼量上來看,Spark應用往往是對等的MR應用的好幾分之一,但裸用Spark API開發高效Spark應用還是需要花些心思的。這就體現出Spark SQL的優勢了:即便用戶寫出的查詢不那麼高效,Catalyst也可以自動應用一系列常見優化策略。

下面舉一個簡單的filter pushdown優化的例子,首先是一段用Spark API寫成的查詢邏輯:

case class Person(name: String, age: Int, salary: Double)

sc.textFile("input.txt")
.map { line =&>
val Array(name, age, salary) = line.split(",")
Person(name, age.toInt, salary.toDouble)
}
.map { case Person(name, _, salary) =&>
(name, salary)
}
.filter(_._2 &> 30000)
.map(_._1)
.collect()

有經驗的程序員會把上述邏輯中的filter挪到第二個map之前,這樣第二個map要處理的元素可能就要少很多(假設月薪大於30,000的不多)。這種情況下,只能依靠程序員自身的經驗來做優化。如果使用Spark SQL,上面這個例子里的邏輯翻譯成HQL相當於:

SELECT name
FROM (
SELECT name, salary
FROM people
) t
WHERE t.salary &> 30000

遇到這樣的查詢時,Catalyst會自動應用filter pushdown優化,將上述查詢在執行計劃層面改寫成與下述HQL等價的查詢:

SELECT name
FROM (
SELECT name, salary
FROM people
WHERE salary &> 30000
)

完整的Spark SQL程序則是:

case class Person(name: String, age: Int, salary: Double)

val people = sc.textFile("input.txt").map {
val Array(name, age, salary) = line.split(",")
Person(name, age.toInt, salary.toDouble)
}

people.registerAsTable("people")

val query: RDD[(String, Double)] = sql(
"""
SELECT name
FROM (
SELECT name, salary
FROM people
) t
WHERE t.salary &> 30000
""")

val result = query.collect()

上面這個例子同時也可以看到,在Spark SQL中可以輕鬆混用SQL/HQL和Spark的RDD API。比如上面的query變數便是一個包含SQL查詢結果的普通RDD對象,可以直接喂入MLlib作為後續機器學習演算法的輸入,而無須額外的跨系統轉儲成本。在單一系統內支持多種分析,這也是Spark最大的優勢之一。

Spark SQL還很新,目前主要精力集中在性能和穩定性方面,功能方面也還不是非常完善,非常歡迎來自社區的貢獻。其實Catalyst/Spark SQL里還有很多有趣的東西,四月份中國Spark技術峰會上會進一步介紹,這裡就不多說了,否則到時候就沒懸念了 :-)


shark維護組織databrick已經發聲明了:

廣而告之:Databricks終止Shark項目,轉至Spark SQL-CSDN.NET


Spark SQL的定位是能在Spark上執行SQL,面向的數據既可以是RDD的,也可以是外部數據源(Hive,Parquet)。

Spark SQL brings native support for SQL to Spark and streamlines the process of querying data stored both in RDDs (Spark』s distributed datasets) and in external sources. Spark SQL conveniently blurs the lines between RDDs and relational tables. Unifying these powerful abstractions makes it easy for developers to intermix SQL commands querying external data with complex analytics, all within in a single application. Concretely, Spark SQL will allow developers to:

  • Import relational data from Parquet files and Hive tables
  • Run SQL queries over imported data and existing RDDs
  • Easily write RDDs out to Hive tables or Parquet files

Shark的代碼我沒具體看過,只使用過。Spark SQL這塊最近看了代碼。我對Spark SQL和Shark的理解是:

Shark對hql的詞法語法解析、邏輯執行計劃生成是依賴hive做的,(優化和物理執行計劃生成不知道Shark自己有沒有介入,在數據的存讀和計算執行過程中有一些優化),在這個過程中,hive的元數據,hive對HCatalog的使用也都是hive本身來做的。Shark主要目的應該是將物理執行從MR變成Spark 上的RDD計算。

另一方面,Spark SQL項目內分了三個模塊,分別是sql,catalyst和hive。Spark SQL在sql的解析、邏輯執行計劃生成、優化、物理執行計劃生成等方面都依賴Catalyst來完成。Spark SQL與Shark有個很大的區別在於介入了邏輯執行計劃的生成和優化,這一部分也是Catalyst存在的原因,也同樣是Catalyst可以帶給Shark的。

這次Spark SQL還增加了一種對Hive的使用方式,就是可以把Spark代碼里的hql直接丟給hive做,我理解是把任務丟給hive做MR,把結果還是返回成RDD,提供進一步計算,也可以直接通過Hive讀取Hive metadata里的表和數據,把數據取過來變成RDD,這是算是RDD和Hive的一種數據和執行的打通方式。


我的理解是shark之前為了減少開發工作量,大幅度借用了hive已經完成的工作。回頭看看當時shark的設計,實在很難想像如果要做一個sql on spark,哪裡還能有見效更快的方法?

而當基於spark的sql這個思路已經被證明很受歡迎,並且已經拿到投資之後,當然重點就從減少開發工作量轉向最好的性能和功能支持發展了。而且從工程角度,不需要依賴於特定的hive實現,部署也會簡單的多。

不要忘記,shark的動機是amplab的phd學霸們要出論文,而spark sql才是在計劃最初就是工業用的產品

所以從未來的應用來看,當然是要用spark sql,但是shark的設計思路對於想要開發demo/實驗性功能的人來說很值得參考。


目前,Spark已經停止更新Shark了,其最後的版本為0.92,可見Spark SQL的發展應該很好~


如果生成的hsql轉給hive,那豈不是多此一舉了,還是轉給自己做的了


看了兩位的評論,感覺sparksql就是新一代的「shark」,大幅擺脫了對hive的依賴,改動和優化很大,我的問題和樓主的困惑一樣:原有的Shark還有存在的必要嗎,是不是SparkSql可完全取而代之?


有個微信群里也有關於大數據這方面的討論,(請加a102420483096手動進群)


推薦閱讀:

hadoop 和spark如何系統的學習?
MapReduce過程中,如果Map之後每個Key對應Value的數量不平衡會不會影響效率?
Spark 為什麼 不允許 RDD 嵌套(如 RDD[RDD[T]])?
怎樣理解spark中的partition和block的關係?
在Spark集群中,集群的節點個數、RDD分區個數、?cpu內核個數三者與並行度的關係??

TAG:大數據 | Spark | Shark |