引言
查詢分析是大資料要解決的核心問題之一,而SQL作為查詢分析中使用最簡單、最廣泛的的語言之一,必然而然的催生了許多支援在Hadoop上使用SQL的系統,這就是所謂的SQL-on-Hadoop系統,其中大衆熟知的Hive就是最早的SQL-on-Hadoop系統。
經過若幹年的發展,SQL-on-Hadoop系統已經百花齊放,按照架構劃分這些系統大緻可以分為以下幾類:
- MapReduce架構系統:如Hive,這類系統是在MapReduce計算架構上封裝了一個SQL語義層,在運作過程中把SQL轉換為MapReduce程式來執行
- MPP架構系統:如Impala、Presto、Drill等,這類系統采用MPP(Massively Parallel Processing)架構,而非MapReduce
- 預計算系統:如Druid、Kylin等,這類系統主要特點是對資料進行預計算,并将結果儲存,而在查詢時直接擷取相應結果值
本文主要是對這些系統做了一個基本總結,并簡單介紹了一些主流系統的架構以及處理流程。下表是按照時間順序,對這些系統的一個概述,包括技術特點和主導公司等。
項目名稱 | 時間點 | 技術特點 | 主導公司 |
---|---|---|---|
Apache Hive | 2008年進入Apache,2010年畢業 | 一款基于HDFS的MapReduce計算架構,提供類SQL的資料查詢功能,本質是将SQL轉換為MapReduce任務運作 | 初期由Facebook開發,後被各大公司廣泛接受 |
Apache Spark | 2010年進入Apache,2014年畢業 | 資料在記憶體中以RDD(Resilient Distributed Datasets)表示,DataFrame是其核心程式設計抽象,同時也支援互動式查詢和流計算 | Databricks |
Cloudera Impala | 2012年進入Apache,2017年11月畢業 | 一款使用C/C++實作的MPP SQL查詢引擎,使用HDFS作為存儲,并支援列存 | Cloudera |
Apache Drill | 2012年進入Apache,2014年畢業 | 以Google Dremel論文為基礎,一個MPP資料查詢引擎,支援schema free的互動式資料查詢 | MapR |
Presto | 2013年開源 | 基于記憶體的計算引擎,本身并不存儲資料,支援跨資料源的級聯查詢 | |
Stinger Initiative | 2013年 | 對Hive的性能優化和提升 | Hortonworks |
Apache Phoenix | 2013年進入Apache,2014年5月畢業 | 建構在HBase上的一個SQL層 | 初期由Salesforce開發 |
Apache Tajo | 基于Hadoop的資料倉庫和SQL資料查詢執行引擎 | 由Database Lab., Korea University開發 | |
Apache Flink | 2014年4月進入Apache,2014年12月畢業 | 流式的資料流執行引擎,基于流計算來模拟批計算,分别提供了流處理和批處理API | Data Artisans |
Apache Kylin | 2014年11月進入Apache,2015年11月畢業 | 使用CUBE技術做多元資料預計算和聚合 | 初期由ebay開發,現由Kyligence主導 |
Apache HAWQ | 2015年進入Apache,2018年5月畢業 | Hadoop原始大規模并行SQL分析引擎,支援ACID事物特性 | |
Apache Trafodion | 2015年進入Apache,孵化中 | HP實驗室 |
Apache Hive是Hadoop生态系統中最早的SQL引擎,它可以将結構化資料檔案映射為一張資料庫表,并提供類SQL查詢功能。Hive本質上是在MapReduce計算架構上封裝了一個SQL語義層,并在運作過程中把SQL轉換為MapReduce程式來執行。
Hive通過使用者互動接口接收SQL後,其Driver結合中繼資料将SQL翻譯成MapReduce程式,并送出到Hadoop中執行,最後将執行結果輸出,其架構如下圖所示:
主要組成部分包括:
- user interface:即使用者接口,包含CLI(指令行),JDBC/ODBC等
- Metastore:即中繼資料,包括表名、表的資料所在目錄等;預設中繼資料存儲在自帶的derby資料庫中,推薦使用MySQL
- Driver:即驅動器,包含以下幾個元件:
- 解析器(SQL Parser):将SQL轉換成抽象文法樹(AST),并對AST進行文法分析
- 編譯器(Compiler):将AST編譯生成邏輯執行計劃
- 優化器(Query Optimizer):對邏輯執行計劃進行優化
- 執行器(Execution):把邏輯執行計劃轉換成可以運作的實體計劃
Hive提供的類SQL查詢功能避免了開發人員書寫複雜的MapReduce程式,極大的簡化了MapReduce程式的開發,大大減少了相應的學習成本。随着技術的不斷進步,Hive的執行引擎也不斷發展,尤其是有了Tez之後,其性能有了很大的改進。不過,其不足依舊很明顯,即處理速度慢,因而比較适合運作在批處理場景中,而不适合互動式查詢等對時延要求高的場景中。
Spark是一個通用的大資料計算架構,期望使用一個技術棧來解決大資料領域包括批處理、流計算、互動式查詢、圖計算和機器學習在内的各種計算任務,其軟體棧如下圖所示:
其中的Spark SQL元件是一個用于處理結構化資料的元件,它吸收了一個叫Shark(Hive-on-Spark)的項目。Spark SQL中最重要的一個概念就是DataFrame,它是帶有Shema資訊的RDD,類似于傳統資料庫中的二維表格。Spark SQL支援将多種外部資料源的資料轉化為DataFrame,包括Json、Parquet等,并可以通過将其注冊為臨時表,然後使用SQL來處理和分析這些資料。Spark SQL的運作流程包含以下幾步,如圖所示:
包含以下幾個步驟:
- SQL語句經過SqlParser解析成UnresolvedLogicalPlan
- Analyzer結合catalog進行綁定,生成LogicalPlan
- Optimizer對LogicalPlan優化,生成OptimizedLogicalPlan
- SparkPlan将OptimizedLogicalPlan轉換成PhysicalPlan
- prepareForExecution()将PhysicalPlan轉換成executedPhysicalPlan
- PhysicalPlan執行得到最終結果RDD
傳統的MapReduce程式中Map和Reduce階段的結果都要寫磁盤,這大大降低了系統性能。Spark使用RDD作為基本資料結構,資料常駐記憶體,是以計算速度得到了很大提高。但是當記憶體不足時,其計算速度會大大降低,甚至容易出現OOM錯誤。
Apache Impala
Apache Impala是一款基于HDFS/HBase的MPP查詢引擎,其架構如下圖所示:
-
Impalad: 即Impala Daemon(Impala守護程序);它運作在叢集的每個node上,負責接收用戶端的查詢請求,對查詢進行并行化處理。其中接收查詢請求的Impalad為Coordinator,Coordinator對查詢語句處理後生成執行計劃,再把執行計劃分發給具有相應資料的其它Impalad執行,其他Impalad執行完成後,把結果發送回
Coordinator,由Coordinator建構最終結果,并傳回給用戶端。另外,Impalad程序也會和Statusstore通信以确認哪些Impalad是可以正常工作的
- Statestore: 負責跟蹤和檢查Impalad健康狀态的程序,由statestored程序表示;它負責處理Impalad的注冊訂閱,并且和各個Impalad程序保持心跳連結
- CLI: 提供給使用者查詢使用的指令行工具(Impala Shell使用python實作),同時Impala還提供了Hue,JDBC, ODBC使用接口
Impala沒有使用MapReduce計算架構,而是使用與商用并行關系資料庫中類似的分布式查詢引擎,并且Impala的中間結果不寫入磁盤,而是通過網絡以流的形式傳遞,這大大降低了IO開銷,因而Impala的查詢速度非常快。但是Impala缺點也很明顯,如對使用者自定義函數支援不好、不支援Transforms、不支援查詢期的容錯等。
Apache Drill是一個分布式的MPP SQL引擎,是開源版本的Google Dremel。它支援對本地檔案、HDFS、HBASE等資料進行資料查詢,也支援對如JSON等schema-free的資料進行查詢,其架構如下圖所示:
從上圖可以看到,Drill的核心是DrillBit,它主要負責接收用戶端的請求,處理查詢,并将結果傳回給用戶端。 Drill的查詢流程包括以下步驟:
- drill用戶端發起查詢,任意DrilBit都可以接受來自用戶端的查詢
- 收到請求的DrillBit成為驅動節點(Foreman),對查詢進行分析優化生成執行計劃,之後将執行計劃劃分成各個片段,并确定合适的節點來執行
- 各個節點執行查詢片段,并将結果傳回給驅動節點
- 驅動節點将結果傳回給用戶端
Presto是一個分布式的MPP查詢引擎,支援多種資料源,包括Hive、RDBMS、Redis等,并且可以跨資料源查詢。Presto的基本架構如下圖所示:
- coodinator:用于解析查詢SQL,生成執行計劃,并分發給worker執行
- discovery server:worker上線後,向discovery server注冊。coodinator分發任務前,需要向discovery server擷取可以正常工作worker清單
- worker:具體執行任務的工作節點
Apache Phoenix是一個運作在HBase上的SQL架構,其本質是用Java寫的基于JDBC API操作HBase的開源SQL引擎,通過Phoenix可以像使用MySQL等關系型資料庫一樣操作HBase中的表。Apache Phoenix支援ACID事務功能的标準SQL,它将SQL編譯成原生HBase的scan語句,其架構如下圖所示:
從上圖可以看到:
- Phoenix的JDBC driver是在HBase的client端
- Phoenix在HBase的RegionServer上
Apache Kylin是一個開源的分布式分析引擎,提供Hadoop/Spark之上的SQL查詢接口及多元分析(OLAP)能力。Kylin的核心是預計算,即對可能用到的度量進行預計算,并将結果儲存為Cube以便查詢時直接通路。Kylin的架構如下圖所示:
- 離線建構部分:根據中繼資料的定義,從資料源(如Hive)抽取資料,并通過MapReduce Job建構Cube,建構後的Cube儲存在HBase中
- 線上查詢部分:使用者通過RESTful API、JDBC/ODBC等接口送出SQL,REST服務把SQL交給查詢引擎處理。查詢引擎解析SQL,生成邏輯執行計劃,之後将其轉化為基于Cube的實體執行計劃,最後讀取預計算生成的Cube并傳回結果
Apache Flink是一個面向分布式資料流處理和批量資料處理的開源計算平台,它能夠基于同一個Flink運作時提供流處理和批處理兩種類型應用的功能。差別于其他流處理系統,Flink作為流處理時,把輸入資料流看做是無界的,而批處理被作為一種特殊的流處理,隻是它的輸入資料流被定義為有界的。
基于同一個Flink運作時(Flink Runtime),Flink分别提供了流處理和批處理API,為了實作API層流與批的統一,Flink提供了一種關系型API,即Table & SQL API。
Apache HAWQ的全稱是Hadoop With Query,是一個Hadoop原生的MPP SQL引擎。HAWQ能直接在HDFS上讀寫資料,而不需要connector,并支援ACID事務特性,其架構如下圖所示:
- HAWQ master:負責處理用戶端送出的SQL,解析優化後向叢集Segment節點下發查詢,合并從各Segemt節點傳回的結果,并傳回最終結果給用戶端。HAWQ master内部由HAWQ Resource Manager,HAWQ Catalog Service,HAWQ Fault Tolerance Service,HAWQ Dispatcher等元件組成。HAWQ master還需要維護global system catalog,global system catalog是系統表的集合,其中包含了HAWQ叢集的中繼資料資訊
- HAWQ segment:叢集的計算節點,本身不存儲任何資料,所有資料都存儲在HDFS上。HAWQ master在分派SQL請求給Segment時會附帶相關的中繼資料資訊,中繼資料資訊包含了表的HDFS URL,Segment通過HDFS URL通路需要處理的資料
- PXF agent:PXF(Pivotal eXtension Framework)的服務。PXF是一個允許HAWQ通路外部系統資料的可擴充架構,其中内置了通路HDFS檔案,HBase表以及Hive表的連接配接器,PXF還可以通過和HCatalog內建來直接通路Hive表
結束語
SQL-on-Hadoop系統經過了若幹年的發展,已經有了很大的提高,但是目前各個系統仍然在不斷完善提高,例如:
- 執行計劃方面:更強的優化器
- 執行效率方面:支援code generation、vectorization等
- 存儲格式方面:支援更高效列存等
未來也會出現更多技術、更多系統。本文主要介紹了目前幾大開源的SQL-on-Hadoop系統及其架構,包括Hive、Spark、Presto、Drill等。