大數據

物化視圖在 SparkSQL 中的實踐

本文轉載自公眾號: 數據湖技術
作者:馬駿傑


什麼是物化視圖

物化視圖主要用於預先計算並保存表連接或聚合等耗時較多的操作的結果,這樣,在執行查詢時,就可以避免進行這些耗時的操作,從而快速的得到結果。物化視圖使用查詢重寫(query rewrite)機制,不需要修改原有的查詢語句,引擎自動選擇合適的物化視圖進行查詢重寫,完全對應用透明。它和視圖的區別在於,物化視圖將存儲實際的數據,而視圖只是存儲SQL語句。使用物化視圖的基本流程為:

  1. 創建物化視圖
  2. Query查詢
  3. 基於物化視圖,對Query進行查詢重寫,生成新的Query
  4. 基於新的Query進行查詢

如下圖,user,item,ui是3張表,先創建物化視圖mv,使用Query查詢時,將基於mv對Query進行重寫,生成新的基於物化視圖的Query,再進行查詢。這個例子中可以看到,在最終生成的Query裡,消除了所有的join操作,將3表join查詢轉換成了單表查詢。對於大數據查詢引擎來說,大表join將會產生shuffle過程,是造成查詢緩慢的瓶頸之一,這種轉換將極大的提升查詢效率。

image.png

物化視圖現狀及實踐目標
傳統數據庫,如Oracle,MSSQL Server等都已經支持物化視圖,但是在大數據領域裡,支持這類預計算優化的有Hive,Kylin,ClickHouse,其中只有Hive是基於物化視圖,而Kylin由於並非將數據存儲在原有數倉中,而是存儲在自定義的介質中(HBase,Parquet等),所以和物化視圖還是有很大的差別。基於使用方式,ClickHouse在使用時需要輸入物化視圖的表名,不能做到查詢時對用戶透明。

SparkSQL目前有哪些預計算相關的優化呢?

已有實現:
  • Cache Table
  • Reuse Exchange (該優化重用同一個Query中相同的表掃描操作)
各大公司的自有實現:
  • Relational cache (阿里巴巴)
  • eBay, 字節跳動等內部數據平臺,在各種場合的分享中,也提到了對SparkSQL進行了物化視圖的優化
Spark社區的相關JIRA(未實現):
  • SPARK-29038: SPIP: Support Spark Materialized View
  • SPARK-26764: [SPIP] Spark Relational Cache
  • SPARK-29059: [SPIP] Support for Hive Materialized Views in Spark SQL

基於目前現狀,我們希望能將物化視圖的優化功能加入到SparkSQL中,並使用Hive對相關元數據進行管理。從實現角度看,Hive的實現是基於Calcite,將Hive的plan轉換成Calcite的結構,使用Calcite的AbstractMaterializedViewRule進行優化後,再轉換回Hive的plan,最終提交給計算引擎進行計算。我們目標是借鑑Calcite的實現方式(基於參考文獻【1】),將物化視圖的優化整合進Spark Catalyst框架。不引入Calcite的優勢是,避免核心功能強依賴於第三方庫,便於後續改動及功能增強。

物化視圖設計詳解

物化視圖的功能將拆分為2部分,分別是SparkSQL + Hive整合,Plan Rewrite,其中Plan Rewrite是作為整個功能的核心模塊,接下來將分別對這2部分進行描述。

SparkSQL + Hive 整合

為什麼選擇Hive2.3

因為Hive是在2.3將物化視圖功能引入(官網裡顯示是 3.0.0版本才被引入),雖然這個版本對於物化視圖支持還不夠完善,但是我們所需要的相關元數據管理已經具備。目前SparkSQL對於Hive的支持只實現到Hive2.3(參考HiveClientImpl),當然,內部Hive3.0還未開始大規模使用也是原因之一。這裡需要注意的是,2.3和3.0版本最主要的區別是存儲Materialized View的字段不同,在2.3中是存儲在View Original Text,而在3.0是存儲在View Expanded Text。

基於Hive的物化視圖DDL命令,在SparkSQL中新增DDL命令,用來管理物化視圖,新增命令如下:

  • create materialized view
  • drop materialized view
  • alter materialized view enable/disable rewrite
  • alter materialized view rebuild

由於物化視圖本質是一種類型的表,所以desc命令同樣適用,無需新增。

在Spark中,HiveShim中並未實現新的物化視圖的元數據接口,需要進行實現,實現後的整合如下圖:

image.png

來看一個實際的例子,使用如下Query創建物化視圖後,

create materialized view mv_q1

STORED AS ORC

AS

SELECT

  d_year
,

  sr_customer_sk AS ctr_customer_sk
,

  sr_store_sk AS ctr_store_sk
,

  sum
(
sr_return_amt
)
 AS ctr_total_return

FROM tpcds_bin_partitioned_orc_2
.
store_returns
,

     tpcds_bin_partitioned_orc_2
.
date_dim

WHERE sr_returned_date_sk 
=
 d_date_sk

GROUP BY d_year
,
 sr_customer_sk
,
 sr_store_sk

使用desc命令展示物化視圖的元數據,結果如下圖:

image.png

需要關注的是,Table Type和View Original Text,和普通表相比存儲了物化視圖相關的信息。在整合完成後,SparkSQL和Hive對於物化視圖的操作就完全打通,創建等操作互相可見。

Plan Rewrite 設計

設計概覽

image.png

上圖展示了Plan Rewrite功能實現涉及的基本流程,其中,Materialized Optimizer作為單獨節點接入到整個SparkSQL流程中,為什麼不和其它優化規則一起併入Optimizer?最主要的原因是,單獨列出來可以使用explain命令對優化後的LogicalPlan進行檢查。物化視圖的優化涉及到大量的代碼,這樣做對於後續的debug也是很有幫助。再回到基本流程,圖的下半部分是關於物化視圖優化的具體步驟,而SessionCatalog那條路徑則是用來從Hive側獲取物化視圖的Query。

優化步驟簡介

關於優化步驟,簡單來說就是提取實際Query和物化視圖的相關信息,進行信息相互的匹配,匹配成功後生成新的Query,再將新的Query轉換成LogicalPlan並返回,如下圖所示:

image.png

由於涉及的細節比較多,上圖並未全部展開,對於圖中列出的信息,其中:

  • table: (x, t1), (t1, t1), (t2, t2):對於每個表,記錄(表名,表名)的鍵值對,如果有別名,則增加(別名,表名)鍵值對
  • output: (t2.id, t2.id), (c, count(1)):對於每個輸出列,保存信息方式如表名
  • equalPreds: (t1.id, (t2.id)), (t2.id,(t1.id)):(col1,(col2,col3))說明col1,col2,col3是相等的列
  • otherPreds: (x.id > 10):除了列相等以外的查詢條件
  • groupby: t1.id:groupBy字段

本文由於不會涉及到實現的細節,所以上述的數據結構僅用來讓大家瞭解在實現過程所用到的部分輔助數據結構。在獲取到相關信息後,將進行匹配及替換過程,最終生成新的Query並返回LogicalPlan。

優化過程中的問題

基於參考文獻【1】,物化視圖在優化過程中需要考慮到一系列問題,接下來將例舉其中的部分:

列相等問題

查詢:

select qed.deptno as ed
from db2.depts qdd join db1.emps qed
wher qed.deptno = qdd.deptno 
group by qed.deptno

物化視圖:

select dd.deptno as md

from db2.depts dd join db1.emps de

where de.deptno = dd.deptno

group by dd.deptno

優化結果:

select mv_db.testmv.`md` AS `ed`

from mv_db.testmv

在上面例子中,查詢的輸出是db1.emps.deptno,物化視圖的輸出是db2.depts.deptno,但是由於都存在列相等條件db1.emps.deptno = db2.depts.deptno,所以這類場景是可以被優化的。

條件匹配問題

查詢:

select deptno

from db1.emps

where(deptno >=0 and deptno <10)

   or(deptno >10and deptno <=20)

   or(deptno >=1and deptno <9)

物化視圖:

select deptno from db1.emps

where(deptno >=0
 
and deptno <10)
   or(deptno >10
 
and deptno <=20)

優化結果:

selec mv_db.testmv.`deptno` AS `deptno`

from mv_db.testmv

where(((mv_db.testmv.`deptno`>=0 AND mv_db.testmv.`deptno`<10)
 OR (mv_db.testmv.`deptno`>10 AND mv_db.testmv.`deptno`<=20))

   OR (mv_db.testmv.`deptno`>=1) AND (mv_db.testmv.`deptno`<9))

條件匹配問題的核心其實是物化視圖包含的數據是否包含所有查詢所需的數據,如果沒有,則優化失敗。

表達式匹配問題

查詢:

select empid +1 as empAdd1, empid as newEmpId
from db1.emps
where deptno =10

物化視圖:

select empid 
from db1.emps 
where deptno =10

優化結果:

select(mv_db.testmv.`empid`+1) AS `empAdd1`,     mv_db.testmv.`empid` AS `newEmpId`
from mv_db.
testmv

條件匹配問題用來判斷查詢所需要的表達式,是否可以通過物化視圖的輸出列進行計算,查詢的表達式不僅包含輸出列,還有where語句中存在的表達式。

多表查詢問題

我們將通過2個例子來了解下這個問題:查詢:

select depts.deptno
from db1.emps join db2.depts on emps.deptno 
= depts.deptno

物化視圖:

select deptno from db1.emps

優化結果:

select db2.depts.`deptno` AS `deptno`
from db2.depts, mv_db.testmv
where(mv_db.testmv.`deptno`= db2.depts.`deptno`
)

上述例子中,查詢的表的數量大於物化視圖,在優化後需要額外join不在物化視圖中的表。

查詢:

select depts.deptno
from db2.depts, db2.dependents, db2.locations
where depts.name = dependents.name
and locations.name = dependents.
name

物化視圖:

select depts.deptno
from db2.depts, db2.dependents, db2.locations
, db1.emps
where depts.name = dependents.name  
and locations.name = dependents.name  
and emps.deptno = depts.deptno

優化結果:?

在這個例子中,查詢的表的數量小於物化視圖,這個時候能優化嗎?由於SparkSQL不支持主外鍵模型,所以這個問題系統是無法判斷的,需要用戶進行判斷物化視圖的數據是否包含了查詢所需的所有數據。我們為這種情況添加了相關參數,默認不支持,但是用戶可以根據需要自行開啟。

聚合函數問題

我們依然通過2個例子來了解下這個問題:

查詢:

select deptno, count(*) as c1
from db1.emps
group by deptno

物化視圖:

select deptno, count(*) as c
from db1.emps
group by deptno

優化結果:

select mv_db.testmv.`c` AS `c1`,mv_db.testmv.`deptno` AS `deptno`
from mv_db.testmv

這個例子中,查詢和物化視圖的groupBy語句裡包含相同的字段,所以優化結果可以直接使用mv_db.testmv.c替換查詢裡的c1。

查詢:

select name, count(*)as c
from db1.empsgroup
 by name

物化視圖:

select deptno, name, count(*)as c
from db1.empsgroup by deptno, name

優化結果:

select sum(mv_db.testmv.`c`) AS `c`,
 mv_db.testmv.`name` AS `name`
from mv_db.testmv
group by mv_dbtestmv.`name`

這個例子中,查詢和物化視圖的groupBy語句裡包含的字段,所以優化結果對於聚合函數需要做額外的處理。

多個物化視圖匹配問題

查詢:

select emps.deptnofrom db2.depts join db1.emps
where emps.deptno = depts.deptno  and emps.deptno >0
group by emps.deptno

物化視圖1:

select depts.deptno from db2.depts join db1.emps
where emps.deptno = depts.deptno
group by depts.deptno

物化視圖2:

select deptno
 from db1.emps

物化視圖3:

select depts.deptno
from db2.depts join db1.emps
where emps.deptno = depts.deptno

物化視圖4(被選中):

select depts.deptno
from db2.depts join db1.emps
where emps.deptno = depts.deptno  and emps.deptno > 0
group by depts.deptno

優化結果:

select mv_db.tmv4.`deptno` AS `deptno`
from mv_db.tmv4

這個例子展示了當多個物化視圖匹配時,會選擇較優的物化視圖進行優化,如何判斷較優目前僅比較優化結果裡join和groupby的數量,相同時再比較filter的數量。由於篇幅有限,這裡不再一一列出更為細節的問題了。

物化視圖實戰

本節將基於TPC-DS(100G),Query17,對物化視圖的實戰能力進行一次測試。

測試用的查詢

由於物化視圖和查詢中同一個Table在from語句裡不能出現多次,所以我們對測試用的查詢做了一些調整,具體如下:

1.    調整前:
2.    SELECT
3.      i_item_id,
4.      i_item_desc,
5.      s_state,
6.      count(ss_quantity) AS store_sales_quantitycount,
7.      avg(ss_quantity) AS store_sales_quantityave,
8.      stddev_samp(ss_quantity) AS store_sales_quantitystdev,
9.      stddev_samp(ss_quantity) / avg(ss_quantity) AS store_sales_quantitycov,
10.      count(sr_return_quantity) as_store_returns_quantitycount,
11.      avg(sr_return_quantity) as_store_returns_quantityave,
12.      stddev_samp(sr_return_quantity) as_store_returns_quantitystdev,
13.      stddev_samp(sr_return_quantity) / avg(sr_return_quantity) AS store_returns_quantitycov,
14.      count(cs_quantity) AS catalog_sales_quantitycount,
15.      avg(cs_quantity) AS catalog_sales_quantityave,
16.      stddev_samp(cs_quantity) / avg(cs_quantity) AS catalog_sales_quantitystdev,
17.      stddev_samp(cs_quantity) / avg(cs_quantity) AS catalog_sales_quantitycov
18.    FROM store_sales, store_returns, catalog_sales, date_dim d1, date_dim d2, date_dim d3, store, item
19.    WHERE d1.d_quarter_name = '2001Q1'
20.      AND d1.d_date_sk = ss_sold_date_sk
21.      AND i_item_sk = ss_item_sk
22.      AND s_store_sk = ss_store_sk
23.      AND ss_customer_sk = sr_customer_sk
24.      AND ss_item_sk = sr_item_sk
25.      AND ss_ticket_number = sr_ticket_number
26.      AND sr_returned_date_sk = d2.d_date_sk
27.      AND d2.d_quarter_name IN ('2001Q1', '2001Q2', '2001Q3')
28.      AND sr_customer_sk = cs_bill_customer_sk
29.      AND sr_item_sk = cs_item_sk
30.      AND cs_sold_date_sk = d3.d_date_sk
31.      AND d3.d_quarter_name IN ('2001Q1', '2001Q2', '2001Q3')
32.    GROUP BY i_item_id, i_item_desc, s_state
33.    ORDER BY i_item_id, i_item_desc, s_state
34.    LIMIT 100
35.    調整後:
36.    SELECT
37.      i_item_id,
38.      i_item_desc,
39.      s_state,
40.      count(ss_quantity) AS store_sales_quantitycount,
41.      avg(ss_quantity) AS store_sales_quantityave,
42.      stddev_samp(ss_quantity) AS store_sales_quantitystdev,
43.      stddev_samp(ss_quantity) / avg(ss_quantity) AS store_sales_quantitycov,
44.      count(sr_return_quantity) as_store_returns_quantitycount,
45.      avg(sr_return_quantity) as_store_returns_quantityave,
46.      stddev_samp(sr_return_quantity) as_store_returns_quantitystdev,
47.      stddev_samp(sr_return_quantity) / avg(sr_return_quantity) AS store_returns_quantitycov,
48.      count(cs_quantity) AS catalog_sales_quantitycount,
49.      avg(cs_quantity) AS catalog_sales_quantityave,
50.      stddev_samp(cs_quantity) / avg(cs_quantity) AS catalog_sales_quantitystdev,
51.      stddev_samp(cs_quantity) / avg(cs_quantity) AS catalog_sales_quantitycov
52.    FROM tpcds_bin_partitioned_orc_100.store_sales,
53.       tpcds_bin_partitioned_orc_100.store_returns,
54.       tpcds_bin_partitioned_orc_100.catalog_sales,
55.       tpcds_bin_partitioned_orc_100.date_dim d1,
56.       tpcds_bin_partitioned_orc_100.store,
57.       tpcds_bin_partitioned_orc_100.item
58.    WHERE d1.d_date_sk = ss_sold_date_sk
59.    AND i_item_sk = ss_item_sk
60.    AND s_store_sk = ss_store_sk
61.    AND ss_customer_sk = sr_customer_sk
62.    AND ss_item_sk = sr_item_sk
63.    AND ss_ticket_number = sr_ticket_number
64.    AND sr_customer_sk = cs_bill_customer_sk
65.    AND sr_item_sk = cs_item_sk
66.    AND d_quarter_name = '2001Q1'
67.    GROUP BY i_item_id, i_item_desc, s_state;

測試用的物化視圖

將創建2個物化視圖用來測試,一個是基於Kylin風格,另一個是更靈活的風格。



1.    物化視圖1:
2.    create materialized view mv_db.mv_100_t17 AS SELECT
3.      i_item_id,
4.      i_item_desc,
5.      s_state,
6.      d_quarter_name,
7.      count(ss_quantity) AS store_sales_quantitycount,
8.      avg(ss_quantity) AS store_sales_quantityave,
9.      stddev_samp(ss_quantity) AS store_sales_quantitystdev,
10.      stddev_samp(ss_quantity) / avg(ss_quantity) AS store_sales_quantitycov,
11.      count(sr_return_quantity) as_store_returns_quantitycount,
12.      avg(sr_return_quantity) as_store_returns_quantityave,
13.      stddev_samp(sr_return_quantity) as_store_returns_quantitystdev,
14.      stddev_samp(sr_return_quantity) / avg(sr_return_quantity) AS store_returns_quantitycov,
15.      count(cs_quantity) AS catalog_sales_quantitycount,
16.      avg(cs_quantity) AS catalog_sales_quantityave,
17.      stddev_samp(cs_quantity) / avg(cs_quantity) AS catalog_sales_quantitystdev,
18.      stddev_samp(cs_quantity) / avg(cs_quantity) AS catalog_sales_quantitycov
19.    FROM tpcds_bin_partitioned_orc_100.store_sales,
20.       tpcds_bin_partitioned_orc_100.store_returns,
21.       tpcds_bin_partitioned_orc_100.catalog_sales,
22.       tpcds_bin_partitioned_orc_100.date_dim d1,
23.       tpcds_bin_partitioned_orc_100.store,
24.       tpcds_bin_partitioned_orc_100.item
25.    WHERE d1.d_date_sk = ss_sold_date_sk
26.    AND i_item_sk = ss_item_sk
27.    AND s_store_sk = ss_store_sk
28.    AND ss_customer_sk = sr_customer_sk
29.    AND ss_item_sk = sr_item_sk
30.    AND ss_ticket_number = sr_ticket_number
31.    AND sr_customer_sk = cs_bill_customer_sk
32.    AND sr_item_sk = cs_item_sk
33.    GROUP BY d_quarter_name, i_item_id, i_item_desc, s_state;
34.    物化視圖2:
35.    create materialized view mv_db.mv_100_t17_2
36.    STORED AS ORC
37.    AS
38.    SELECT
39.      i_item_id,
40.      i_item_desc,
41.      s_state,
42.      d_quarter_name,
43.      ss_quantity,
44.      sr_return_quantity,
45.      cs_quantity
46.    FROM tpcds_bin_partitioned_orc_100.store_sales,
47.       tpcds_bin_partitioned_orc_100.store_returns,
48.       tpcds_bin_partitioned_orc_100.catalog_sales,
49.       tpcds_bin_partitioned_orc_100.date_dim d1,
50.       tpcds_bin_partitioned_orc_100.store,
51.       tpcds_bin_partitioned_orc_100.item
52.    WHERE d1.d_date_sk = ss_sold_date_sk
53.    AND i_item_sk = ss_item_sk
54.    AND s_store_sk = ss_store_sk
55.    AND ss_customer_sk = sr_customer_sk
56.    AND ss_item_sk = sr_item_sk
57.    AND ss_ticket_number = sr_ticket_number
58.    AND sr_customer_sk = cs_bill_customer_sk
59.    AND sr_item_sk = cs_item_sk;

注意的是物化視圖1裡的輸出列和groupby語句裡增加了d_quarter_name字段,由於這個變化,所以針對物化視圖1的查詢將變更為:

  1.    SELECT i_item_id,
2.      i_item_desc,
3.      s_state,
4.      count(ss_quantity) AS store_sales_quantitycount,
5.      avg(ss_quantity) AS store_sales_quantityave,
6.      stddev_samp(ss_quantity) AS store_sales_quantitystdev,
7.      stddev_samp(ss_quantity) / avg(ss_quantity) AS store_sales_quantitycov,
8.      count(sr_return_quantity) as_store_returns_quantitycount,
9.      avg(sr_return_quantity) as_store_returns_quantityave,
10.      stddev_samp(sr_return_quantity) as_store_returns_quantitystdev,
11.      stddev_samp(sr_return_quantity) / avg(sr_return_quantity) AS store_returns_quantitycov,
12.      count(cs_quantity) AS catalog_sales_quantitycount,
13.      avg(cs_quantity) AS catalog_sales_quantityave,
14.      stddev_samp(cs_quantity) / avg(cs_quantity) AS catalog_sales_quantitystdev,
15.      stddev_samp(cs_quantity) / avg(cs_quantity) AS catalog_sales_quantitycov
16.    FROM tpcds_bin_partitioned_orc_100.store_sales,
17.       tpcds_bin_partitioned_orc_100.store_returns,
18.       tpcds_bin_partitioned_orc_100.catalog_sales,
19.       tpcds_bin_partitioned_orc_100.date_dim d1,
20.       tpcds_bin_partitioned_orc_100.store,
21.       tpcds_bin_partitioned_orc_100.item
22.    WHERE d1.d_date_sk = ss_sold_date_sk
23.    AND i_item_sk = ss_item_sk
24.    AND s_store_sk = ss_store_sk
25.    AND ss_customer_sk = sr_customer_sk
26.    AND ss_item_sk = sr_item_sk
27.    AND ss_ticket_number = sr_ticket_number
28.    AND sr_customer_sk = cs_bill_customer_sk
29.    AND sr_item_sk = cs_item_sk
30.    AND d_quarter_name = '2001Q1'
31.    GROUP BY d_quarter_name, i_item_id, i_item_desc, s_state;

邏輯計劃比較

下圖展現了3種情況下,最終的邏輯執行計劃,可以看到物化視圖優化後,從多表join已經變成了單表查詢,而物化視圖2比物化視圖1多了Aggregate運算,這個是由groupBy產生。
image.png

Spark UI統計比較

下圖展示了3種情況下,各自的執行job/stage,注意,測試時開啟了Spark Adaptive Execution特性。
image.png

性能數據比較

下圖展示了3種情況下,各自的耗時數據,其中Spark統計耗時是來自Spark UI,而這個數據向我們展示了物化視圖在查詢效率方面的可能性,明明計算只用了0.6s,為什麼查詢需要6s?在追求更快的響應時間時,這些額外的消耗是否能優化呢?比如資源調度耗時等,這個也是作為一個後續的優化方向。
image.png

物化視圖 VS Kylin

物化視圖屬於一種基於預計算方式的查詢優化,也是我們常說的空間換時間。在大數據領域,提到查詢預計算,Kylin肯定會被提及,該項目在各個領域中有了很多的成功應用案例。那麼物化視圖和Kylin相比,區別在哪裡呢?接下來將分別和Kylin的兩種結構,做一些比較。比較內容僅限於離線預計算及查詢,畢竟Kylin還支持適時建cube等功能。

Kylin on HBase

E85C9025-B511-49a6-BE83-A36F87932B60.png
基於上述比較,物化視圖使用更為靈活,方便,也易於維護,但是Kylin在查詢效率,特別是計算量不大的查詢(如,沒有distinct),有著巨大的優勢。對於這兩者的應用更多要依賴於實際使用場景,比如:

報表類的場景,維度度量都不會經常變化,前端對於延時要求又比較高,那Kylin是一種很好的選擇。在上節例子中,mv_100_t17就是模擬Kylin創建物化視圖,在目前的SparkSQL實現中,延遲和Kylin差距還是非常大,但是相信經過適當的優化,性能會有很大的提升。

數據探索類的場景,如果在探索的過程中經常會嘗試新的數據維度,那麼物化視圖就能更好的滿足這種靈活性的需求。可以想象下這樣的狀況,分別通過Kylin和物化視圖,對於多張事實表和維度表進行預計算,忽然在數據分析過程中,還想增加維度信息。對於Kylin來說,重新建Cube,而物化視圖則支持直接查詢。當預計算成本很高時,這樣的靈活性還是能給分析工作帶來便捷的。在上節的例子中,mv_100_t17_2這類物化視圖,就能很好的體現這種靈活性。

Kylin自帶Cube管理界面,便於用戶對Cube進行管理,而物化視圖目前需要用戶自行搭建管理平臺或使用腳本方式,這個在使用時也應該加以考慮。

Kylin on Parquet

從2020/04開始,Kylin社區開始逐步推進下一代架構,Kylin on Parquet,主要的原因是為了解決HBase運維不便,單點計算等問題。在捨棄HBase後,Cube的存儲將使用Parquet,而查詢將使用Spark引擎。雖然該架構還在推進演變中,但相比Kylin on HBase,這個架構和SparkSQL物化視圖更為接近,物化視圖也能將數據以Parquet格式存儲,查詢引擎使用的是SparkSQL。為了保證低延時,Kylin對Spark進行了優化(比如,從yarn獲取資源後,不再釋放,消除資源申請耗時),而這類優化對於SparkSQL是通用的,相信物化視圖也能從中獲取收益。假如在延時上Kylin不能佔據絕對的優勢,那我認為物化視圖帶來的靈活性是Kylin目前做不到的,畢竟cube的數據即使存儲在parquet中也不能和Hive中的數據進行交互。

總結

本文介紹了數據庫常用的優化方式,物化視圖,在SparkSQL這個流行的大數據查詢引擎上的相關實踐,包括了實現的架構,實現的簡介,實戰中的表現等。同時也和業界大佬Kylin進行了對比,展示了這類優化方式的適用場景。後續有計劃將該優化在Spark社區進行開源,和大家一起將SparkSQL打造成更好的大數據計算引擎。

參考資料

【1】Optimizing Queries Using Materialized Views: A Practical, Scalable Solution


阿里巴巴開源大數據技術團隊成立Apache Spark中國技術社區,定期推送精彩案例,技術專家直播,問答區近萬人Spark技術同學在線提問答疑,只為營造純粹的Spark氛圍,歡迎釘釘掃碼加入!
image.png

對開源大數據和感興趣的同學可以加小編微信(下圖二維碼,備註“進群”)進入技術交流微信群。
image.png

Apache Spark技術交流社區公眾號,微信掃一掃關注

image.png

Leave a Reply

Your email address will not be published. Required fields are marked *