基於 Impala 的高性能數倉實踐之物化視圖服務

本文將主要介紹 NDH Impala 的物化視圖實現。

接上篇,前兩篇分別講了執行引擎和虛擬數倉,它們是讓一個 SQL 又快又好地執行的關鍵。但如果某些 SQL 過於複雜,比如多張大表進行 Join 並有大量的聚合類操作,那麼再優秀的執行引擎也無法保證能夠秒級執行完成,虛擬數倉的彈性擴展能力也很難及時跟上,這正是物化視圖能夠發揮作用的場景。

1 物化視圖簡介

在計算機領域,物化視圖是一個數據庫對象,結構化保存了一個 SQL 查詢的結果集,創建物化視圖的過程可稱爲物化,是預計算的一種形式。物化視圖是一個比較寬泛的概念,可能是遠端數據的一份本地拷貝,也可能是一個表或多表 Join 後某些行 / 列的子集,也可以是將聚合函數作用到表或 Join 結果後的彙總類信息。

1.1 物化視圖分類

根據物化視圖中原始數據表的個數,可分爲單表和多表物化視圖;根據物化視圖 SQL 中是否存在聚合類操作,可分爲明細和聚合物化視圖;根據物化視圖的結果集在更新時是否需要全量刷新,可將其分爲全量和增量物化視圖,後者又可稱爲分區物化視圖,增量數據寫入新分區中。

1.2 特點與作用

普通視圖僅表示一個 SQL 語句,是個邏輯概念,而物化視圖則有實體對象 / 表與之對應。這樣在執行查詢時,就可以通過查詢對應的物化視圖表數據,從而快速得到查詢結果。物化視圖使用查詢重寫機制,當執行查詢時,引擎自動選擇合適的物化視圖進行查詢重寫,完全對應用透明。

一般用於進行性能加速,具有比較廣泛的使用場景,如果業務查詢存在如下特徵,即可嘗試用物化視圖進行加速:比如查詢耗時較多且查詢頻次較高、相同或相似的查詢多併發或週期性發生、業務對查詢結果的數據實時性沒有過於嚴格的要求,允許分鐘或小時級的延遲等。具體業務方面,在數倉領域,T+1 類 BI 報表是典型的可以通過物化視圖進行優化查詢的場景。

1.3 使用效果評估

物化視圖使用得當能夠數倍,甚至數十倍提升查詢性能,但其也不是萬能的,如果不分場景盲目創建物化視圖,其結果可能適得其反。一方面是因爲物化視圖的創建和更新有成本,另一方面,判定 SQL 是否命中的邏輯也在性能敏感的代碼路徑上引入了額外的耗時。

筆者認爲,使用物化視圖的效果評價需要考慮 2 個方面:首先,其是否帶來了查詢的性能提升。這是最基本的目標;其次,是否降低了集羣總的資源消耗,包括計算資源和存儲資源。這是進階目標,在每個物化視圖都有大量的查詢命中時,將會明顯減少每個查詢對 CPU 和內存資源的需求,同時也不再需要訪問原始表,減少 IO 資源消耗。

1.4 使用現狀

物化視圖是進行查詢性能優化的重要手段,傳統的商業數據庫,比如 Oracle、IBM 和 SQL Server,以及目前商業數倉系統,比如 Snowflake、AnalyticDB 等,均具有強大的物化視圖能力。

目前開源的數倉系統,在物化視圖支持程度上相對不足,Doris、Clickhouse、Druid 等暫時僅支持單表聚合類物化視圖(或稱爲聚合索引),也有數倉引擎已經在開發多表物化視圖,比如 Meta 的 PrestoDB 等。網易 NDH Impala 在物化視圖能力建設上投入較早,目前已在生產環境上規模使用,本章的後續小節主要介紹 NDH Impala 的物化視圖實現和實踐。

2 Impala 物化視圖

2.1 設計架構

在設計 Impala 物化視圖系統時,秉持了儘可能通用的原則,希望其不僅僅能夠用於改寫 Impala 查詢 SQL,未來能夠方便的集成到其他的查詢引擎上。下圖所示爲物化視圖設計架構圖,包括獨立的物化視圖服務、嵌入在 Impala Coordinator 中的物化視圖改寫模塊和用於優化物化視圖的 Impala 管理服務器。

物化視圖服務提供了多種物化視圖管理的 API,包括視圖的創建、定義更新、數據更新 / 同步、啓用 / 禁用、視圖信息展示、視圖使用統計和視圖刪除等。Impala 管理服務器保存的歷史查詢信息爲物化視圖服務的視圖創建、定義更新和視圖管理提供數據支撐。物化視圖服務使用 MySQL 作爲元數據庫,包括了視圖定義、狀態和使用統計等信息。Impala Coordinator 節點集成了物化視圖透明改寫模塊,用於判斷查詢 SQL 是否能夠命中某個 / 某些物化視圖,若命中,則對其進行透明改寫。

2.2 視圖創建

NDH Impala 提供兩種物化視圖創建模式,分別適用於網易數帆的有數 BI 場景和通用場景,兩者均需使用 NDH Impala 專有的管理服務器,通過歷史查詢信息優化來物化視圖定義。前者基於有數 BI 的數據模型和圖表歷史查詢行爲來生成物化視圖 SQL,後者則是通過分析歷史查詢信息來提取 SQL 模板信息,爲滿足要求的 SQL 模板創建物化視圖。下面主要介紹有數 BI 場景下的視圖創建,包括預檢查、物化視圖 SQL 優化和更新。

預檢查

預檢查用於在物化視圖創建之前,提前剔除掉不合理或暫不支持的創建請求。主要有以下幾種情況:

(1)判斷是否爲實時或準實時表。Impala 物化視圖服務暫不支持實時場景,所以,如果待優化的 BI 數據模型或 SQL 模板中存在 Kudu 表或 Arctic/Iceberg 表,則拒絕創建請求。

(2)判斷是否能夠進行模糊匹配。主要包括聚合或多表關聯時條件自由篩選場景,舉多表外關聯爲例,假設表 t1 和 t2 均爲分區表,分區字段均爲 dt,但兩表並沒有通過 dt 字段進行關聯,用戶在查詢時會靈活地爲 t1 和 t2 進行 dt 分區各取不同的值 / 範圍,由於外連接的非關聯字段過濾在關聯前和關聯後進行是不等價的,因此無法模糊匹配。對於聚合場景,若物化視圖對錶 user 的 age 列取平均值,若查詢對 user 進行了篩選,顯然 age 列的平均值會失效。

(3)判斷是否適合用物化視圖進行優化。引起查詢慢的原因很多,物化視圖適合對查詢本身慢進行優化,對於偶發或波動類的因素,其優化效果並不明顯。這些因素包括存儲層性能抖動(比如 HDFS 的 DN 或 NN 性能波動)、HMS 元數據加載(未命中 catalog 緩存導致查詢時需即時加載)、排隊執行(查詢併發超閾值或內存資源不夠)、集羣網絡抖動(網絡擁塞等)。物化視圖服務通過從 Impala 管理服務器獲取該數據模型或 SQL 模板的歷史查詢 profile 信息來進行前述因素的判定。

對於上述情況,物化視圖創建請求直接拒絕,並返回拒絕的原因。

SQL 優化

若是 BI 的數據模型場景,對通過了預檢查的創建請求,還需要對其傳入的 “裸” 物化視圖 SQL(模型 SQL)進行優化。我們先說原因,再說如何進行優化。

爲什麼要進行物化視圖 SQL 優化?本質上說是爲了提升前述的物化視圖使用效果。從實踐經驗看,數據模型 SQL 中可能涉及 TB 甚至 PB 級別的大表,這些表一般是按日期,比如天進行分區,模型中會對多個分區表按分區字段進行關聯。大部分情況下,在數據模型層面並沒有約束大表的分區範圍,也就是說,如果完全按數據模型 SQL 進行物化視圖構建,所需消耗的計算和存儲資源可能是單個圖表查詢的數十、上百倍甚至更高倍數。爲了提升數個圖表查詢的性能而消耗過多的資源顯然是不可取的。而現實情況是,圖表查詢中的分區範圍往往是有明顯的規律性的,一般集中在最近一個季度,大部分都是一個星期內的時間,如下圖所示:

本着最優的投入產出比,我們就可以基於以往的查詢規律,將物化視圖的作用域縮短到某個分區範圍內,比如昨天、最近一週、最近一個月等等。

那麼具體是如何做的呢?NDH Impala 做的很多優化都用到了 Impala 查詢 Profile,在實現物化視圖系統時也不例外。在進行物化視圖 SQL 優化時,會從歷史查詢中篩選出屬於該數據模型的所有圖表查詢 SQL,分析其 Profile 信息,進一步過濾出待優化的 SQL 集合。這些 SQL 一般滿足如下一個或多個條件:查詢耗時超過閾值(已排除隊列等待、元數據加載等因素)、消耗的內存資源超過閾值、掃描數據量超閾值、掃描的行數超閾值等。

經過前述條件篩選後,還可根據圖表查詢的觸發類型等維度區分優化的優先級,比如用戶觸發的圖表查詢優先級高於 BI 後臺進行結果預緩存的查詢。

對於篩選出來的 SQL 集合,逐個解析 SQL 語句,提取各事實和維度表的分區範圍,並按大小進行排序。默認取最大的分區範圍作爲物化視圖的有效範圍,若該範圍過大,則根據配置的參數選擇更加合適的分區範圍,比如選擇 90% 以上查詢都在其中的範圍值。

多物化視圖

基於上面的優化邏輯,對一個數據模型,會創建至少一個物化視圖,但也可能創建多個物化視圖,這主要跟用戶在該數據模型上創建的圖表特點有關,比如,往往需要給列表篩選器單獨創建物化視圖。

先解釋下什麼是列表篩選器。下圖是用於展示 Impala 慢查詢的圖表,可分爲紅框和藍框兩部分,其中紅框用於進行過濾條件篩選,篩選的結果在藍框中展示。紅框中有倒三角下拉標記的這些控件就是列表篩選器。

以 hostname 篩選器爲例,其用於查看某幾個特定 Coordinator 上的慢查詢。要對其進行篩選,首先就需要獲取可選的 Coordinator 節點,這就需要執行一條查詢 SQL:對存放 Impala 歷史查詢信息的 basic_info 表的 hostname 列全表掃描並 group by 取結果。由於默認是不帶分區過濾的全表掃描,因此無法命中物化視圖,且由於全表掃描,查詢性能較差,因此會專門爲沒有分區過濾條件的一個或多個列表篩選器創建物化視圖。

分區物化視圖

爲了能夠提高物化視圖的數據更新效率,在創建物化視圖時會判斷是否能夠對物化視圖數據進行增量更新。物化視圖服務通過解析物化視圖 SQL,判斷各表是否用分區字段進行關聯,若是,則可以創建分區物化視圖,在進行數據更新時,只需要處理前一天新產出的數據。

SQL 更新

SQL 更新指的是物化視圖創建後,在使用過程中,根據用戶 / 業務查詢行爲的變化,動態調整物化視圖 SQL。可以通過物化視圖的查詢命中率來評估是否需要調整。這裏所說的命中率是指同個數據模型下的圖表查詢,能夠命中物化視圖的百分比。

假設某個數據模型的物化視圖,創建後的命中率一直高於 80%,若最近幾天命中率下降到 50% 以下,那麼可能有兩種情況導致,一種是數據模型被修改,另一種是圖表或篩選條件發生變化。對於前一種情況,有數 BI 產品會通過服務視圖服務提供的接口自動觸發物化視圖 SQL 更新。

對於後一種情況,需要物化視圖服務通過後臺的分析線程週期性分析查詢命中率,在命中率明顯變差後,觸發物化視圖 SQL 更新。

2.3 視圖使用

判斷一個查詢能否命中某個物化視圖並在命中後自動改寫使其查詢物化視圖表,這是個數據庫領域十分有技術含量的工作,有多篇頂級論文提出了不同的解法。在 Impala 物化視圖服務中,命中判斷和透明改寫的核心是基於 Apache Calcite 提供的兩種算法 [1]。但光靠 Calcite 現有的能力還不足以滿足線上規模使用的要求,Impala 物化視圖服務在此基礎上做了大量的優化。本小節先簡述 Calcite 改寫實現,再介紹所做的增強。

Calcite 透明改寫能力

總的來說,目前有三種物化視圖改寫實現,分別是基於語法、基於規則和基於結構進行查詢命中判斷並改寫。其中,基於語法的改寫方式通過文本匹配或者語法匹配實現,將查詢的文本與物化視圖的文本或語法樹進行比較,完全匹配即可進行改寫。該方式實現難度低、改寫效率最高,但只能匹配完整的查詢語句或子查詢,適用範圍太小。

Apache Calcite 實現了基於規則和基於結構的物化視圖改寫方式,詳見 “Substitution via rules transformation”[2] 和 “Rewriting using plan structural information”[3]。

基於規則的改寫方式使用範圍較廣,可以對大量重寫,功能實現也較爲簡單,改寫匹配速度快,其侷限是改寫依賴轉換規則來尋找等價關係,因此需要窮舉所有可能的轉換關係來實現複雜視圖的重寫。一些複雜的視圖不可能窮舉所有的等價關係,例如存在很多的 Join 聯接或者複雜的 Project 關係,基於規則的改寫適用的範圍取決於規則的數量。

基於結構的改寫方式由微軟在 2001 年 SIGMOD 論文《Optimizing queries using materialized views: A practical, scalable solution》[4] 系統化的提出。其將查詢表示爲 SPJG 標準形式 (Join-Select-Project-GroupBy),提取查詢中的 Join,Projects,Filters,Grouping 和 Aggregations 五種表達式,運用一系列的步驟分別與物化視圖對應的表達式進行匹配並得到補償表達式。

基於結構的改寫相比基於規則的方式更容易擴展,使用範圍更廣,不足之處在於搜索成本較高。在實踐中發現,使用後者對複雜 SQL(比如存在 10 + 以上表關聯)進行改寫時,其性能遠不如前者,尤其是該查詢 SQL 還命中了多個物化視圖時,可能無法達到優化查詢性能的目的,甚至適得其反。因此,Impala 物化視圖服務會同時使用基於規則和基於結構的改寫實現,並使用前者作爲默認的改寫方式。

改寫能力優化

爲了增強改寫能力,提高改寫性能,Impala 物化視圖服務對改寫方式進行了優化,主要包括元數據緩存、命中預判定、支持更多 SQL 語法和改寫校驗等,如下圖所示。

元數據緩存

前文的物化視圖服務架構圖提到物化視圖信息(既物化視圖元數據)是持久化在 MySQL 中的,而對用戶查詢進行透明改寫需要用到物化視圖元數據,顯然,每次進行改寫時都從 MySQL 加載元數據會對改寫性能造成很大影響,因此,需要在 Impala Coordinator 緩存物化視圖元數據信息。

進一步,原生的 Calcite 改寫框架在執行改寫前,需要基於物化視圖元數據信息(MaterializationActor.Materialization)動態生成物化視圖改寫對象(RelOptMaterialization),這是一個比較耗時的過程,假設某個用戶查詢有 10 個候選物化視圖,僅構造物化視圖改寫對象可能就需要耗費數百毫秒甚至數秒時間。爲了降低改寫過程的耗時,需在 Coordinator 提前構造 RelOptMaterialization 並將其緩存。

爲了確保緩存的元數據是最新的,Coordinator 會每隔數秒(可配置)從 MySQL 獲取新增或更新過的物化視圖信息,構建 MaterializationActor.Materialization 和 RelOptMaterialization 對象並替換原有的緩存對象。

命中預判定

Calcite 物化視圖改寫過程是串行的,也就是系統會逐一判斷每個候選的物化視圖是否能夠成功改寫物化視圖。元數據緩存能夠縮短每次判斷的時間,但無法減少判斷次數。爲此,我們加入了命中預判定來減少候選的物化視圖個數。

目前採用的命中預判定策略類似上述的基於語法的改寫實現,如果查詢 SQL 和物化視圖 SQL 一樣,無需走命中判定和改寫,直接返回改寫後 SQL。更通用的方法是根據 SQL 語句自身的一些特點,設置一些規則,提前過濾掉部分不可能用於改寫的物化視圖。這些規則包括但不限於:

  • 判斷滿足物化視圖中涉及的表均在查詢 SQL 中
  • 判斷滿足查詢返回的 selectList 屬於物化視圖 selectList 的子集
  • 若查詢 SQL 存在 Sort 算子(定義見下文),判斷是否滿足 Sort 算子的校驗
  • 若匹配的物化視圖對象數量仍超過閾值,再通過歸一化 SQL 進行匹配篩選

通過以上預判定,可以大大減少參與改寫的物化視圖數量,提高改寫效率。而且,可以提前識別不可能命中物化視圖的查詢 SQL,減少無效的改寫行爲。

語法 / 算子支持

Calcite 雖提供了基於規則和結構的改寫方式,但在每種實現中,支持的語法和算子還不夠多,比如不支持改寫帶外連接(outer join)的查詢,不支持分組和排序相關的算子等。此外,Impala 上大量的內置 UDF 函數顯然也是不支持的。這些都嚴重限制了物化視圖在業務場景中的使用,均需要我們進行增強。

Calcite 不支持多表外連接場景,我們通過二次開發,在確保改寫結果正確性的基礎上,支持以下情況的物化視圖改寫:

除上圖之外,從表(左連接時爲右表,右連接時爲左表)子查詢過濾有個特殊情況可以允許改寫,即當從表子查詢過濾條件全爲關聯(on)字段且這些字段過濾條件和主表過濾一致。

Calcite 也還未支持查詢中包含 Sort 算子(包括排序、分頁,即 order by/limit/offset)的場景,但目前 NDH Impala 支撐的業務查詢,絕大部分都帶有 Sort 算子。我們增加了對包含 Sort 算子的查詢進行改寫的支持。實現上,目前是通過改寫前移除查詢 SQL 中的 Sort 算子,改寫後校驗補償 Sort 算子的方案來實現。

帶 Group 算子的查詢存在改寫後丟失 Group 算子的問題,而 NDH Impala 支撐的業務查詢中帶有 Group 算子的查詢比例較高。因此,對 Group 算子改寫也進行了完善,補償方式上與 Sort 算子相似。

改寫校驗和回退

爲了確保經過 Calcite 改寫的 SQL 是正確的,需對改寫後 SQL 進行校驗,比如確認是否包含物化視圖表。通過驗證後,會增加 SQL 註解,用於標識該 SQL 非原始 SQL。若改寫結果校驗不通過,或改寫過程中出現任何異常,或改寫後 SQL 在 Impala 進行解析和鑑權等處理時出現任何異常,都會替換回原始查詢 SQL,確保查詢正常執行。

2.4 數據更新

與基於 Calcite 的透明改寫模塊不同,NDH Impala 物化視圖系統的數據更新模塊是全新開發的,提供了多種更新方法,處理了更新失敗場景並設計了可擴展的元數據更新方案。

更新方法

物化視圖表的數據在創建後不能一成不變,當原始表有新數據寫入或對歷史數據進行更新後,需要儘快更新物化視圖表數據,確保命中物化視圖後查到最新的結果。對於像 Impala 這樣的存算分離查詢引擎,數據的寫入和更新一般基於 Hive 或 Spark,並不能天然地感知到表中數據的變化,在我們的方案中,提供了四種數據更新的方法,分別是依託有數大數據平臺的離線數據產出日誌、依託 NDH 的 Hive Metastore(HMS) DDL 日誌、兜底的定期檢查原始表的數據文件修改時間,最後還有手動更新。

有數大數據平臺的數據血緣模塊能夠根據數據產出的上下游關係,推送離線數據產出日誌,物化視圖服務訂閱產出消息,將其持久化到 MySQL 的產出日誌表中,再由更新線程消費這些產出日誌,驅動包含該原始表的一或多個物化視圖進行數據更新。若原始表沒有配置數據血緣,通過 NDH HMS 組件的 DDL 操作日誌來驅動。相對來說,基於產出日誌的更新效率更高。

如果表沒有數據血緣,數據寫入和更新也不走 HMS,那麼上述兩種更新策略均失效。此時,需爲物化視圖配置數據更新時間窗,更新線程在物化視圖進入時間窗後會定時檢查物化視圖中各原始表數據目錄的數據文件,檢查修改時間,若大於上次物化視圖更新時間,這需驅動物化視圖更新。

更新失敗處理

若由於某種原因,物化視圖更新失敗,則需要進行重試,若仍然失敗,則需要將該物化視圖失效掉,禁止查詢 SQL 命中該物化視圖。之後在由管理員介入進行問題排查。

元數據更新

前文提到的物化視圖的創建、定義更新、數據更新和禁用等行爲,均需要創建或更新物化視圖元數據。尤其是數據更新時,還需要修改物化視圖用於進行命中判定的物化視圖 SQL。下面舉個簡單的例子:

SELECT XXXXXX
FROM `music_db`.`xxxx` AS `t1`
INNER JOIN `music_iplay`.`xx` AS `t2` ON CAST(`t1`.`userid` AS VARCHAR(255)) = `t2`.`user_id`
LEFT JOIN `music_iplay`.`xxx` AS `t3` ON `t1`.`day` = `t3`.`dt` AND `t1`.`unionid` = `t3`.`union_id`
LEFT JOIN `music_iplay`.`xxxxxxx` AS `t4` ON `t2`.`live_type` = `t4`.`live_type` AND `t2`.`dt` = `t4`.`dt` AND `t2`.`user_id` = CAST(`t4`.`user_id` AS VARCHAR(255))
WHERE `t1`.`day` = partitionColumn_1

上圖是一個物化視圖的定義 SQL,有 4 個原始表,分別進行內連接和左連接,其中 t1 表爲 T+1 分區表,分區字段 day。“partitionColumn_1” 是數據更新站位標誌,表示查詢 t1 表的最近分區(昨天)。與之對應,物化視圖改寫 SQL 爲(假設今天爲 2022-8-11):

SELECT XXXXXX
FROM `music_db`.`xxxx` AS `t1`
INNER JOIN `music_iplay`.`xx` AS `t2` ON CAST(`t1`.`userid` AS VARCHAR(255)) = `t2`.`user_id`
LEFT JOIN `music_iplay`.`xxx` AS `t3` ON `t1`.`day` = `t3`.`dt` AND `t1`.`unionid` = `t3`.`union_id`
LEFT JOIN `music_iplay`.`xxxxxxx` AS `t4` ON `t2`.`live_type` = `t4`.`live_type` AND `t2`.`dt` = `t4`.`dt` AND `t2`.`user_id` = CAST(`t4`.`user_id` AS VARCHAR(255))
WHERE `t1`.`day` = '2022-08-10'

到了第二天(2022-8-12),t1 表的 2022-8-11 號分區數據產出,物化視圖完成數據更新後,需要更新改寫 SQL 的 WHERE 條件(WHERE t1.day = '2022-08-11')並持久化到 MySQL 中。

SELECT XXXXXX
FROM `music_db`.`xxxx` AS `t1`
INNER JOIN `music_iplay`.`xx` AS `t2` ON CAST(`t1`.`userid` AS VARCHAR(255)) = `t2`.`user_id`
LEFT JOIN `music_iplay`.`xxx` AS `t3` ON `t1`.`day` = `t3`.`dt` AND `t1`.`unionid` = `t3`.`union_id`
LEFT JOIN `music_iplay`.`xxxxxxx` AS `t4` ON `t2`.`live_type` = `t4`.`live_type` AND `t2`.`dt` = `t4`.`dt` AND `t2`.`user_id` = CAST(`t4`.`user_id` AS VARCHAR(255))
WHERE `t1`.`day` = '2022-08-11'存放物化視圖元數據的MySQL表中包含createTime和updateTime兩列,分別表示物化視圖元數據的創建和最後一次更新時間,Impala集羣各Coordinator通過這兩個字段即可獲取新增或修改過的元數據,更新Coordinator內存中的物化視圖緩存,確保進行查詢命中判定和改寫時使用的是最新的元數據。

2.5 視圖管理

Impala 物化視圖提供了管理頁面,能夠進行視圖信息展示,使用統計並進行一些常用的視圖操作。如下圖示例:

通過管理頁面可以看到每個視圖的基本信息,包括創建和最近更新時間、視圖是否啓用、視圖表的記錄數和數據量等。通過詳情頁能進一步查看視圖定義,包括建表 SQL、更新 SQL 和改寫 SQL 等。管理頁面還提供物化視圖的命中明細信息,可以查看每個物化視圖命中了哪些用戶查詢,展示那些查詢的基本信息等,如下所示:

通過物化視圖命中率統計還能夠查看視圖的使用效果,如下所示:

通過管理頁面提供的信息,用戶能夠刪除一些性價比較低的物化視圖,如近期不再有查詢命中,或者消耗資源過多等。

就目前來說,Impala 物化視圖服務更多還是聚焦在優化和增強核心模塊,包括視圖創建、改寫和更新的效率。在管理頁面上提供的信息還比較有限。

3 實踐和總結

Impala 物化視圖服務上半年在網易雲音樂的 BI 重點報告場景規模化落地使用,明顯改善了在 BI 報表預緩存未命中場景下的報表查看性能體驗。在落地過程中,也遇到了不少問題。

3.1 問題和挑戰

遇到的問題是多方面的,在技術上主要集中在視圖的命中判定和改寫、視圖數據更新上。經過充分調研和對比,確定前者基於 Calcite 快速獲得能力,避免重複造車。後者由於平臺依賴性較強,採用全自研的方式。

更多的困難來自於落地使用。在剛開始落地使用時,遇到直接基於 BI 數據模型創建的物化視圖性價比較低問題(創建和更新物化視圖所需資源過多,帶來的查詢性能提升不足以抵消增加的成本),問題原因主要是模型上沒有設置分區表的分區過濾條件,比如 t1 表保存了近 3 年的數據分區,但報表上用到的 t1 數據僅爲最近 1 個月。由於模型上未對分區進行篩選,導致直接基於模型 SQL 創建物化視圖時會全量物化近 3 年所有的數據,其資源浪費不言而喻。在此情況下,我們引入了視圖創建審覈機制,先確認模型 SQL 的合理性,若未帶分區約束,則通過 Impala 管理服務器保存的歷史查詢來確定所需的分區範圍,物化視圖使用的性價比明顯提升。

但審覈需要人工查看每個數據模型下發的 SQL,統計查詢的分區區間,性價比雖提升了,但人力投入增加了,因此又逐步開發了自動進行歷史查詢的分區範圍統計的能力,提高創建效率。引入歷史查詢來確定分區範圍提高了性價比,但用戶的查詢行爲不會一成不變,因此,又有了週期性的重新獲取分區範圍的思路,並逐步提高自動更新能力。

3.2 使用思考

物化視圖是一種有效的性能提升手段,無需贅言,但從實踐來看,物化視圖具有較高的使用門檻,尤其是通過多表連接的物化視圖,往往需要有數據庫背景的研發或運維才能用好。原因如下:首先,物化視圖通過 SQL 來表示定義,這對於不熟悉 SQL 的用戶不友好;其次,只有充分了解用戶具體會執行哪些 SQL,創建的物化視圖纔能有足夠高的查詢命中率;最後,只有不斷識別用戶查詢 SQL 的條件變化,才能使物化視圖維持較高的查詢命中率。

在大數據場景,如果數據分析師具備較強的 SQL 能力,那麼物化視圖可作爲一種輕量級 ETL 手段,用來快速進行查詢性能加速。這個主要是從敏捷和靈活性角度出發來考慮的,假設數據分析師直接通過多表連接進行自助分析和 Ad-Hoc 查詢,由於表的數據量大或表關聯多,可能性能會比較差,影響數據分析效率。若分析師向數據加工團隊提需求建個新表用於分析查詢,這需要新增一個 ETL 任務,數據加工團隊可能需要排期來做,從提出需求到新表就緒可能需要數個工作日甚至數週時間,若查詢的需求多而易變,那對數據加工團隊是個不小的負擔。這種情況下,若數據分析師具備較強的 SQL 能力,可以發揮物化視圖服務的靈活性,無需數據加工團隊介入,新表(物化視圖表)的就緒時間也可以大大縮短。

但在更普遍的情況下,分析師對 SQL 較爲陌生,比如使用 BI 產品進行數據分析時,傳統的物化視圖技術並不適合。要用好物化視圖,需要在數據庫 / 數據倉庫和最終用戶之間有個中間的溝通角色,對於傳統的關係型數據庫,這個角色就是數據庫管理員(DBA),其職能包括審覈業務的表結構、分析慢 SQL、巡檢數據庫服務日誌和數據庫性能調優等等,DBA 掌握了使用物化視圖進行查詢性能優化所需的信息。在大數據分析領域往往存在 DBA 角色缺失的情況,客觀原因很多,不是本文討論重點,在此不展開。

在這樣的背景下,爲了發揮物化視圖的能力,需要對其進行一些變革。路徑很多,其中就包括讓物化視圖更加智能,知道應該創建什麼樣的物化視圖,知道什麼時候應該及時調整物化視圖,這正是我們在物化視圖系統實現後期做的嘗試。但這條路肯定是漫長的,如何儘可能避免對具體業務場景的依賴還需不斷探索。比如 Impala 物化視圖服務爲有數 BI 產品做的智能化方案,並不一定在其他產品上有同樣的效果。另一種變革的方式是從產品側驅動,比如有數 BI 產品提供物化視圖能力,優勢包括相比數倉系統更瞭解用戶(報表)查詢行爲、能夠用比 SQL 更直觀的方式來表示物化視圖、在 BI 系統產生 SQL 前即可完成查詢的改寫、可以做得更加通用不依賴具體的數據源等。

4 小結

本文先簡要介紹了物化視圖定義、分類、特點和作用等基本知識,再重點介紹了 NDH 在 Impala 上實現的物化視圖系統,包括基於 Apache Calcite 進行二次開發的透明改寫能力,基於離線數據產出日誌、HMS DDL 日誌等方式驅動的物化視圖數據自動更新服務,以及視圖管理模塊。進一步介紹了在網易雲音樂場景落地實踐及經驗教訓,思考如何才能高效發揮物化視圖的查詢性能優化能力。最後需要說明的是,以上均爲筆者個人的一些實踐和體會,歡迎各位大佬提供意見建議、批評指正。

參考鏈接:

  • [1] https://calcite.apache.org/docs/materialized_views.html

  • [2] https://calcite.apache.org/docs/materialized_views.html#substitution-via-rules-transformation

  • [3] https://calcite.apache.org/docs/materialized_views.html#rewriting-using-plan-structural-information

  • [4] https://www.cnblogs.com/listenfwind/p/16029792.html

作者簡介

榮廷,網易數帆數據庫技術專家,10 年 + 數據庫相關工作經驗,目前主要負責高性能數倉和雲原生數據庫研發工作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章