如何能更好的運用與監控sparkSQL?或許我們改更深層次的瞭解它深層次的原理是什麼。之前總結的已經寫了傳統數據庫與Spark的sql解析之間的差別。那麼我們下來直切主題~
如今的Spark已經支持多種多樣的數據源的查詢與加載,兼容了Hive,可用JDBC的方式或者ODBC來連接Spark SQL。下圖爲官網給出的架構.那麼sparkSql呢可以重用Hive本身提供的元數據倉庫(MetaStore)、HiveQL、以及用戶自定義函數(UDF)及序列化和反序列化的工具(SerDes).
下來我們來細化SparkContext,大的流程是這樣的:
1、SQL語句經過SqlParser解析成Unresolved LogicalPlan;
2、使用analyzer結合數據字典(catalog)進行綁定,生成Resolved LogicalPlan;
3、使用optimizer對Resolved LogicalPlan進行優化,生成Optimized LogicalPlan;
4、使用SparkPlan將LogicalPlan轉換成PhysiclPlan;
5、使用prepareForException將PhysicalPlan轉換成可執行物理計劃。
6、使用execute()執行可執行物理計劃,生成DataFrame.
這些解析的過程,我們都可以通過監控頁面觀察的到。
下來我們先從第一個Catalog開始,什麼是Catalog?它是一個字典表,用於註冊表,對標緩存後便於查詢,源碼如下:
這個類呢,是個特質,定義了一些tableExistes:判斷表是否存在啊,registerTable:註冊表啊、unregisterAllTables:清除所有已經註冊的表啊等等。在創建時,new的是SimpleCatalog實現類,這個類實現了Catalog中的所有接口,將表名和logicalPlan一起放入table緩存,曾經的版本中呢,使用的是mutable.HashMap[String,LogicalPlan]。現在聲明的是ConcurrentHashMap[String,LogicalPlan]
然後呢,我們來看一下詞法解析器Parser的實現。在原先的版本中,調用sql方法,返回的是SchemaRDD,現在的返回類型爲DataFrame:
你會發現,調用了parseSql,在解析完後返回的是一個物理計劃。
我們再深入parse方法,發現這裏隱式調用了apply方法:
下來我們看一下,它的建表語句解析,你會發現其實它是解析了物理計劃,然後模式匹配來創建表:
最後調用了RefreshTable中的run方法:
那麼創建完表了,下來開始痛苦的sql解析。。。上傳說中的操作符函數與解析的所有sql函數!
一望拉不到底。。。這個Keyword其實是對sql語句進行了解析:
然後拿一個select的sql語法解析爲例,本質就是將sql語句的條件進行了匹配,過濾篩選:
一個select的步驟包括,獲取DISTINCT語句、投影字段projection、表relations、where後的表達式、group by後的表達式,hiving後的表達式、排序字段ordering、Limit後的表達式。隨之就進行匹配封裝操作RDD,Filter、Aggregate、Project、Distinct、sort、Limit,最終形成一顆LogicalPlan的Tree.
那麼join操作,也包含了左外連接、全外連接、笛卡爾積等。
好的,既然sql的執行計劃解析完了,下來該對解析後的執行計劃進行優化,剛纔的解析過程將sql解析爲了一個Unresolved LogicalPlan的一棵樹。下來Analyzer和optimizer將會對LogicalPlan的這棵樹加入各種分析和優化操作,比如列剪枝啊 謂詞下壓啊。
Analyzer將Unresolved LogicalPlan與數據字典(catalog)進行綁定,生成resolved LogicalPlan.然後呢Optimizer對Resolved LogicalPlan進行優化,生成Optimized LogicalPlan.
這裏的useCachedData方法實際是用於將LogicalPlan的樹段替換爲緩存中的。具體過濾優化看不懂啊TAT 算了。。第一遍源碼,講究先全通一下吧。
下來,一系列的解析啊、分析啊、優化啊操作過後,因爲生成的邏輯執行計劃無法被當做一般的job來處理,所以爲了能夠將邏輯執行計劃按照其他job一樣對待,需要將邏輯執行計劃變爲物理執行計劃。
如下圖,你注意哦,配置文件中shufflePartition的個數就是從這裏傳進來的。
這裏面真正牛逼變態的是BasicOperators。它對最常用的SQL關鍵字都做了處理,每個處理的分支,都會調用planLater方法,planLater方法給child節點的LogicalPlan應用sparkPlanner,於是就差形成了迭代處理的過程。最終實現將整顆LogicalPlan樹使用SparkPlanner來完成轉換。最終執行物理計劃。
參考文獻:《深入理解Spark:核心思想與源碼分析》