Hive 原理 | Apache Hive 聯(lián)邦查詢 Query Federation
平臺團(tuán)隊(duì)一般會部署所有這些系統(tǒng),使應(yīng)用程序開發(fā)人員可以靈活地選擇,以滿足他們業(yè)務(wù)分析需求所需的功能。
使用 Apache Hive 3.0 和 SQL 統(tǒng)一訪問
但是我們也知道,如果我們需要將不同存儲來源的數(shù)據(jù)進(jìn)行關(guān)聯(lián),我們需要對數(shù)據(jù)進(jìn)行提取,并放到同一種存儲介質(zhì)里面,比如都放到 HBase 中,然后再進(jìn)行關(guān)聯(lián)操作。大家可以看出,這種數(shù)據(jù)割裂,會對我們的數(shù)據(jù)關(guān)聯(lián)分析帶來很大的麻煩,如果我們能夠使用一種查詢引擎分別查詢不同數(shù)據(jù)源的數(shù)據(jù),然后直接進(jìn)行關(guān)聯(lián)操作,這將帶來巨大的效率提升。這就是本文介紹的 JDBC Storage Handler,詳見 HIVE-1555。
從 JdbcStorageHandler 名字我們就可以看出,其功能應(yīng)該和 HBaseStorageHandler 類似,也就是可以在 Hive 中使用標(biāo)準(zhǔn)的 JDBC 方式讀取存儲在不同數(shù)據(jù)存儲里面的數(shù)據(jù)。比如我們可以在 Hive 中分別讀取 MySQL 和 Phoenix 里面的數(shù)據(jù),然后進(jìn)行關(guān)聯(lián)。其提供高效,統(tǒng)一的 SQL 訪問 - 開箱即用。這樣做的好處是巨大的:
單個 SQL 方言和 API
統(tǒng)一安全控制和審計(jì)跟蹤
統(tǒng)一控制
能夠組合來自多個來源的數(shù)據(jù)
數(shù)據(jù)獨(dú)立性
需要注意的是,目前 JdbcStorageHandler 僅僅支持從 JDBC 數(shù)據(jù)源讀取數(shù)據(jù),還不支持支持將數(shù)據(jù)寫入到 JDBC 數(shù)據(jù)源。

JdbcStorageHandler 支持 CBO
使用 JdbcStorageHandler 從 JDBC 數(shù)據(jù)源讀取數(shù)據(jù)時,一種簡單的方式是直接讀取全量的數(shù)據(jù);并將其全部加載到 Hive。這種方式雖然很簡答,但是卻會帶來性能問題。
基于這些原因,Hive 依賴 storage handler interfaces 以及 Apache Calcite 的 CBO 實(shí)現(xiàn)了智能的算子下推功能。這樣可以將查詢規(guī)則下推到 JDBC 數(shù)據(jù)源,在 JDBC 數(shù)據(jù)源層面上進(jìn)行一些過濾,再將計(jì)算結(jié)果返回給 Hive,這樣可以減少數(shù)據(jù)的量,從而提高查詢效率。
算子下推這個功能不限于 SQL 系統(tǒng),比如我們可以將算子下推到 Apache Druid 或者 Apache Kafka。在查詢 Apache Druid 里面的數(shù)據(jù)時,Hive 可以將過濾和聚合操作下推到 Druid,生成 JSON查詢,并將其發(fā)送到引擎公開的 REST API。另一方面,如果我們查詢 Kafka 里面的數(shù)據(jù)時,Hive 可以直接過濾相關(guān)的分區(qū)或者偏移量,有選擇地從系統(tǒng)中的主題讀取數(shù)據(jù)。
假設(shè)我們在 MySQL 或者 PostgreSQL 里面有 store_sales、 store_retuens 和 date_dim 三張表,然后我們有以下的查詢:
SELECT FLOOR(d_timestap TO DAY),SUM(ss_sales_price) AS sum_salesFROM store_sales, store_returns, date_dimWHERE ss_item_sk = sr_item_sk ANDss_ticket_number = sr_ticket_number ANDss_sold_date_sk = d_date_sk ANDss_store_sk = 410GROUP BY FLOOR(d_timestap TO DAY)ORDER BY sum_sales DESCLIMIT 100;
上面這條 SQL 在優(yōu)化前的執(zhí)行計(jì)劃,如下:

其中灰色的框框是在 MySQL 或者 PostgreSQL 里面執(zhí)行的,橘色的是在 Hive 執(zhí)行的。從上圖可以看出,三次掃描的文件直接返回到 Hive 處理,這樣效率是很低下的,其實(shí)我們可以對其進(jìn)行算子下沉優(yōu)化,經(jīng)過 Apache Calcite 的 CBO 優(yōu)化之后,執(zhí)行計(jì)劃如下:

對應(yīng)的 SQL 執(zhí)行如下:
// 如果是 PostgreSQL JDBC 數(shù)據(jù)源:SELECT DATE_TRUNC('DAY', "d_timestap"),SUM("ss_sales_price") AS "sum_sales"FROM "store_sales", "store_returns", "date_dim"WHERE "ss_item_sk"= "sr_item_sk" AND"ss_ticket_number"= "sr_ticket_number" AND"ss_sold_date_sk"= "d_date_sk" AND"ss_store_sk"= 410GROUP BY DATE_TRUNC('DAY', "d_timestap")ORDER BY "sum_sales" DESCLIMIT 100;// 如果是 MySQL JDBC 數(shù)據(jù)源:SELECT DATE_FORMAT(`d_timestap`, '%Y-%m-%d 00:00:00'),SUM(`ss_sales_price`) AS `sum_sales`FROM `store_sales`, `store_returns`, `date_dim`WHERE `ss_item_sk`= `sr_item_sk` AND`ss_ticket_number`= `sr_ticket_number` AND`ss_sold_date_sk`= `d_date_sk` AND`ss_store_sk`= 410GROUP BY DATE_FORMAT(`d_timestap`, '%Y-%m-%d 00:00:00')ORDER BY `sum_sales` DESCLIMIT 100;
上面的這些操作直接在對應(yīng)的 JDBC 數(shù)據(jù)源上執(zhí)行,然后 Hive 再調(diào)用 JDBC_Scan 將查詢結(jié)果保存到對應(yīng)的 Sink 中。
如何使用 JdbcStorageHandler
說了這么多,那么我們該如何使用 JdbcStorageHandler 呢?為了使用它,我們需要在 Hive 里面創(chuàng)建一張外部表,具體如下:
CREATE EXTERNAL TABLE iteblog_jdbc(name string,age int,gpa double)STORED BY 'org.apache.hive.storage.jdbc.JdbcStorageHandler'TBLPROPERTIES ("hive.sql.database.type"= "MYSQL","hive.sql.jdbc.driver"= "com.mysql.jdbc.Driver","hive.sql.jdbc.url"= "jdbc:mysql://www.iteblog.com/sample","hive.sql.dbcp.username"= "iteblog","hive.sql.dbcp.password"= "iteblog_hadoop","hive.sql.table"= "STUDENT","hive.sql.dbcp.maxActive"= "1");
正如上述所示,Create Table 當(dāng)前需要指定 JDBC 表的模式。HIVE-21060 引入了一種可以對基于 JDBC 外部表自動發(fā)現(xiàn)模式的功能,這樣我們就不必在 Create Table 命令中聲明它。
HIVE-21059 的工作是對外部 Catalog 的支持。外部 Catalog 將允許在 Metastore 中創(chuàng)建指向外部 MySQL 數(shù)據(jù)庫的 Catalog。并且通過此 Catalog,我們可以在 Hive 查詢中使用里面的所有表。
