StarRocks 如何借助物化視圖加速數據分析
一、StarRocks數據湖分析
1、StarRocks 3.0 Overview
StarRock3.0之前定位于實時數倉,主要有以下幾方面的能力:
- 實時寫入:從Kafka、Flink等系統實時插入、更新、刪除數據的能力。
- 批量導入:從 S3、Hadoop、Spark 等各種系統批量導入數據的能力。
- 實時引擎:具備實時存儲引擎和實時查詢引擎,在dashboard、BI、Ad-hoc query等各種場景中,都有比較好的性能和統一性。
StarRocks3.0推出了新的數據湖分析功能,支持Hive、Iceberg、Hudi,和MySQL等傳統DB外表,加上StarRocks本身的外表,使得StarRocks 能夠作為一個統一的查詢引擎,去查詢各種數據源。基于這些能力,我們希望把 StarRocks 打造成一個實時的Lakehouse產品,更好地整合數據湖和數據倉庫這兩種產品概念。
2、StarRocks LakeHouse
LakeHouse可以分為傳統數倉和數據湖兩大塊:
- 傳統數倉:用戶一般會進行數據清洗、寬表加工以及聚合,它的數據質量通常比較好,不用太擔心數據格式問題,因此查詢性能比較好。StarRocks對執行引擎、數據存儲格式、自帶的向量化引擎、實時更新引擎、存儲引擎以及各種執行算子等做了很多優化,實時更新的性能通常可以達到秒級。
- 數據湖:它的優勢是Table format、File format和生態等方面比較open,能夠很容易地接入各種查詢引擎、存儲引擎,所以它能夠成為很多企業的統一存儲;另外它比較適合于作為source of truth的存儲,比如整個企業里的數據統一放在數據湖里面,然后在上層基于這個數據底座去做更多的數據加工跟處理。數據湖的擴展性較好、性價比比較高,它可以是基于S3等大數據生態技術演進過來的,可以基于HDFS、S3等存儲介質。
湖倉目前看來還是有較大gap的、割裂的兩個場景,StarRocks做了很多技術和Feature,去整合這兩種場景,從早期的Warehouse,到3.0做了較大的架構升級,具備了很好的彈性能力。支持存算分離,可以由原生存儲變成S3。支持多種部署方式,可以選擇線下部署,也可以選擇K8s等部署方式。支持數據庫查詢能力,可以作為一個查詢引擎去查詢數據湖。最終希望打造云原生彈性擴展能力,更好地整合成LakeHouse的產品形態。
3、StarRocks LakeHouse - Catalog
StarRocks3.0之前需要手動創建外表DDR來查詢外部數據源,在表很多的時候操作非常繁瑣。3.0的Catalog功能可以直接查詢Hive、Iceberg、Hudi、Deltalake、ES、Mysql、Oracle、Postgres和文件等各種數據源,覆蓋了大部分的數據使用場景。
只需要執行create external Catalog命令,就可以連到Hive Metastore自動獲取元數據,然后就可以直接查詢其中的數據。除此之外另一種場景是在S3上放了一堆文件,但沒有將其組織成Iceberg的format,也可以創建Catalog直接去查詢。
在 External Catalog 的基礎上,結合 StarRocks 的內表存儲,兩種數據源可以 Join 起來同時查詢。由于內表有自己的存儲引擎,具有較好的實時性,可以服務實時workload;同時External Table可以用于存儲歷史數據,這樣就可以聯合使用多種不同的存儲引擎,來覆蓋更多的使用場景。
4、StarRocks LakeHouse - Trino 兼容
Trino、Presto有自己的SQL方言和許多自定義函數,而StarRocks目前主要兼容的是MySQL語法和協議。如果用戶已經過了POC階段,正在生產系統使用Trino、Presto等查詢引擎,想要遷移到StarRocks就會有很多的工作,雖然不用遷移數據,但是需要改造很多業務SQL。
為此StarRocks做了兼容Trino的feature,在SQL parser中支持MySQL和Trino 兩種方言,使用統一的執行計劃,目前已經覆蓋了99%的語法。用戶只需要將方言切換為StarRocks,就可以實現無縫遷移,獲得數倍的性能提升。
5、StarRocks LakeHouse - 極速查詢性能
數據湖由File format和Table format兩部分組成,File format通常會用比較高效的ORC、parquet,Table format通常會用Iceberg、Hudi。
數據湖跟內表存儲引擎理念比較接近,沒有太多本質差別,但是在具體的細節上還是有些差別的,比如說文件格式、文件壓縮效果、IO效果以及整體性能等。HDFS和S3等不同的存儲系統雖然可以提供統一的接口,但它們是有性能差異的,HDFS通常在Latency上會比S3的性能稍微好一些,有些場景下S3會有更好一些。ORC的IO counter可能比parquet要多非常多,也就是parquet可以IO size更大一些。
考慮到這些情況,StarRocks內部做了非常多的IO優化,去克服不同系統之間的性能差異。
上圖是用eBPF之類的工具觀察到的結果,可以看出在數據湖場景下更加IO密集,傳統數倉場景下往往是計算密集。有些用戶的寫數系統比較復雜多樣,數據格式質量不那么好,產生了很多parquet小文件。有些用戶ORC的stripe size設置得非常小,如果按傳統策略每個row group里面讀每個column,它的IO會非常小可能就幾KB,效率非常低,我們也不能把IO粒度擴大到文件級別,因為可能某一個文件非常大。
StarRocks針對不同IO密集場景做了優化。
如果column size非常小就合并IO,一次讀取多個column。
如果文件非常小,就一次讀取整個文件,即便文件中有一些數據可能并不需要,但在做了這樣一個合并之后,總IO次數會少非常多。
如果使用了S3存儲,不管你怎么優化,當訪問它的冷數據的時候,它的IO消耗一定會非常高,最好的優化方式是把數據cache在本地。相較于Presto、Trino會用一些三方組件去做數據cache, StarRocks 希望把系統架構做得更簡單一些,所以自己實現了一套協同memory和disk的cache系統,數據會先cache在memory中,當memory 不夠時數據會溢出到disk上。通常來說大部分workload都會有一個相對比較小的working set,比如有幾百GB的數據要分析,當多次查詢后,大部分數據都能夠命中cache,從而得到比較好的查詢性能。
除此之外 StarRocks 也做過一些算法層面的IO優化,比如延遲物化技術,會根據查詢條件中的where條件先把某一列查出來,再造一個過濾去讀其它列。還有Top N算子,也可以做延遲物化,后面我們可能也會在join也支持延遲物化技術。
綜合使用各種IO優化技術,可以很大程度上減少文件IO。在同樣的數據集、同樣的資源規模下,StarRocks查詢Iceberg比Trino快3-5倍。在大部分用戶案例中,從Trino切換到StarRocks都會有一個非常明顯的性能提升,像TPC-H其實是一個相對沒有那么復雜的數據集,如果用戶的實際業務中有一些特別復雜的SQL,它會有更加明顯的性能提升。
6、StarRocks LakeHouse - 統一開放
StarRocks在架構層面和功能技術層面做了很多整合,比如物化視圖、Catalog、IO優化以及Trino兼容等,希望這些技術能夠整合起來,打造成統一開放的Lakehouse架構。
StarRocks可以作為查詢引擎去查詢數據湖中的數據,替換Spark、Flink等相對比較老的組件。StarRocks 也有自己的存儲引擎,它可以提供 Colocate能力,以及用戶指定的分區、排序、分桶能力,和實時場景下需要的實時更新以及索引的能力。
綜合使用這些技術,使得用戶可以讓一部分workload放在數據湖里,繼續使用Spark、Flink做加工處理,另一部分更偏實時的workload放在內表里,然后用 StarRocks 作為統一的查詢入口,也可以讓實時workload通過StarRocks寫入。結合起來,比較好地實現了實時 LakeHouse這樣的架構。
二、StarRocks 物化視圖
1、StarRocks Materialized View
物化視圖的語法有幾個部分:
partition by:對物化視圖分區,和StarRocks內表一樣,可以按照時間等維度進行分區。分區后可以對查詢裁剪,避免訪問不需要的數據,比如按天分區后就只需要刷當天的數據,歷史數據不需要去touch。還可以進行分區級的數據自動刷新、數據變更的自動訂閱,實現比較好實時性。
Refresh:支持全量刷新、增量刷新、定時刷新、手動刷新等多種方式。滿足不同業務場景的需求。
resource group:把物化視圖跟其它workload更好地整合在同一個系統、同一個集群里。因為用戶的查詢是一種偏前端的workload,而物化視圖的維護是偏后端、資源非常密集的workload,所以如何把這兩種整合到一起,穩定地跑到同一個集群里面,是一個很大的技術難點。所以我們這里選擇用 resource group 技術來實現資源隔離。
查詢語句:支持aggregation、join等查詢語句。
對不同的查詢語句類型可以使用不同的刷新方式,如果是簡單的聚合查詢可以增量刷新,如果有join或者更復雜的語句就要全量刷新。未來StarRocks會逐步擴展物化視圖的增量刷新能力,支持更多的復雜使用場景,比如增量的 join 窗口,類似Flink 的增量計算等等。
生產環境中有很多適合用物化視圖的場景,例如:
增量聚合:很多業務報表會對immutable的event、log數據做sum、distinct、bitmap、Hyperlog等聚合,這類數據一般數據量非常大、寫入TPS高,所以不適合全量刷新。之前常用Flink來做增量計算,像sum、bitmap去重以及Hyperlog等,現在也可以用StarRocks的增量物化視圖來支持。
數倉建模:物化視圖的語法非常適合替代傳統ETL用來建模。業務有時可能不太關心增量刷新還是全量刷新,也不太關心數據之間的依賴關系如何表達、如何調度,就可以使用DBT這種工具直接用物化視圖去建模,它還可以屏蔽底層的刷新方式。
透明加速:用戶可以透明地創建出一個物化視圖,然后利用優化器的查詢改寫能力,改為查詢物化視圖來實現很好的加速效果。
數據湖加速:數據湖查詢往往是IO密集型的,一般可以使用cache來優化,但如果數據量非常大就無法cache在本地。這時可以借助物化視圖來預計算,計算結果的數據量通常會小幾個數量級,再把計算結果cache到本地,就可以很好地加速數據湖的查詢。
2、MV - 數倉建模
傳統數倉建模可以分ODS、DWD、DWS、ADS幾層,每層可能都會用到Hive、Sqoop以及Flink等ETL工具,現在也可以用StarRocks物化視圖技術來構建。從ODS到DWD往往是聚合和清洗,這一層可以用物化視圖的SQL謂詞和增量聚合技術來構建。再往上可能會做寬表join以及面向具體業務的報表,往往需要比較復雜的join,或者窗口函數的計算,也可以用物化視圖來表達。
它帶來價值是能夠簡化架構的復雜度,不需要在外部維護很多的數據組件去做加工,如果維護了這些數據組件,不僅要使用物理資源去部署運行,還需要部署一些調度、監控的組件去支持,這樣的架構是比較復雜的。如果遷移到物化視圖上面來,就只需執行幾條SQL,不需要額外維護組件,物化視圖還維護了調度關系。
另外還能充分利用StarRocks執行引擎的性能優勢,如果使用Hive等外部系統,數據可能先要過一遍Hive,中間的計算開銷以及IO開銷就會非常的消耗資源,然后再往下游系統寫數據,它的IO又會多了幾倍,一旦有很多的IO開銷以及組件,整體性能就很難優化,非常消耗資源,ETL任務的實時性也很難保障。
遷移到StarRocks就可以很好地解決這些問題,主要用到下面幾個關鍵技術:
- 支持多數據源:可以基于內表、數據湖外表和JDBC外表等創建物化視圖,比如可以對MySQL、Postgres創建物化視圖,把數據同步到內部來,這樣就可以不用直接查外部數據了。
- 維護分區關系:對內表和外表的分區關系進行維護,使得全量刷新可以依靠分區去做更細粒度的數據刷新和物化視圖維護。
- 任務調度:物化視圖join表的時候可以顯示聲明依賴關系,被join的表更新完成后才刷新視圖。如果有多張表作為事實表,還可以使用接口手動控制調度、定制業務集。
- 資源隔離:在使用物化視圖替代傳統數倉建模的時候,只需要添加一個新的resource-group,不需要部署新的集群,讓多個workload跑在同一個系統集群中。
上圖中T1是事實表,T2是維度表,列舉了一些分區刷新的經典場景:
事實表細粒度刷新:維度表的變化頻率是相對比較低的,如果事實表做了比較細粒度的分區,比如天級、小時級或分鐘級的分區,在事實表刷新之后,基于分區就可以發現物化視圖對應的某一個分區也需要更新,那就只需要刷新一個分區,代價是相對比較低的。
維度表精準刷新:最經典的場景是刷新整個物化視圖,代價相對較大。有些業務像酒店餐飲是可以不回刷數據的,那么可以精細化的排除某些維度,不觸發回刷。也有一些業務,希望回刷比如一個月的數據,那么可以精準的控制回刷幾個分區。
自動刷新:StarRocks支持訂閱外表分區的數據變更,當發現Hive等外表分區變更后,可以自動刷新物化視圖對應的分區。
3、MV - 彈性資源隔離
StarRocks實現了統一的架構,能夠同時運行Ad-hoc query、Dashboard、Realtime、Batch等多個workload。Realtime物化視圖時效性要求通常比較高,比如實時看板一般是分鐘級,所以資源消耗比較大。Batch物化視圖允許慢一點一般是天級,通常是在半夜定時去跑,所以不需要占用非常多的資源。那么如何資源隔離,使不同的workload不會互相影響,就成為了一個難題。目前StarRocks用了資源組軟性隔離和Warehouse硬性隔離兩個技術來實現資源隔離。
資源組軟性隔離:用戶可以使用默認資源組,或者根據業務需要創建資源組,非常細膩的控制每個視圖的CPU、Memory、Disk等資源的最大配額占比。當只有1個workload 時允許跑到100%,當有多個workload時,就根據配額的比例分配資源,因為是軟性,所以加起來可以超過100%。
Warehouse硬性隔離:在云原生架構實現了無狀態計算節點的架構。物化視圖可以放在獨立的節點運行,將資源徹底隔離開來。Warehouse 本身是彈性的,可以隨時創建、釋放。
4、MV - 透明查詢加速
在BI 報表場景的SQL很多是系統自動生成的,而且通常很復雜,用戶很難通過修改SQL的方式來進行調優,所以需要一種類似于傳統數據庫索引的透明加速能力。
物化視圖針對SPJG(select、project、join、group by)場景,支持查詢改寫加速。比如有兩表的join再聚合的query,我們可以創建一個邏輯一樣的物化視圖,在query時直接scan這個物化視圖,這是exactly match的。如果還有聚合計算,或者聚合key、表達式有區別,那么可以在這個物化視圖的基礎上做二次的聚合、join計算。
案例1:聚合上卷改寫
上圖右邊是物化視圖,有時間和city兩個維度。可以采用類似某些系統的Cube來加速查詢,在創建Cube的時候就把所有維度都預計算出來,后面的查詢幾乎不需要做任何計算。但是如果維度很多,會導致維度組合數量爆炸。物化視圖可以把常見的維度預聚合,比如把時間和城市預聚合,比如一天有幾億數據,按天聚合后數據量會少幾個量級,帶來的效果非常顯著。
上圖左邊是三個實際的查詢,查詢語句不需要跟物化視圖一樣,否則就比較雞肋了。大部分查詢的維度組合是比較靈活的,維度也不一定和物化視圖一致,所以需要上卷以及更多的探索。示例1的查詢按照時間維度聚合count,count是可以上卷的,只需要把物化視圖按照city聚合count一次,所以優化器會自動改寫為基于物化視圖的上卷。示例2按照city聚合也是一樣可以上卷。上卷之后可以獲得更多的維度組合,有比較好查詢加速效果,同時也會兼顧靈活性,還有一些特殊的case是做count distinct,需要結合Bitmap技術,在底層創建物化視圖的時候同時創建bitmap,然后在上面就可以做更多的維度的組合了。
案例2:寬表join改寫
join是非常常見的數據加工方式,寬表join的物化視圖可能把事實表和多個維度表join起來。查詢的時候比較靈活,可能join結果并不需要所有維度,只需要join其中一部分。因為join類型有很多,inner join跟outer join不一樣,一對一join跟一對n join也不一樣,會有一些參數和其他的語法去適配不同的場景,可能把inner join改成其他join方式,也可能完全改寫到物化視圖上去,剔除掉其中不需要訪問的那些數據。
5、MV案例 - 實時精準去重
國內某共享出行公司有幾十個實時看板,需要做精確的count distinct,運營人員要求數據新鮮度達到分鐘級、并發達到100。之前維護了很多Flink job做增量計算,結果發現直接去現算幾乎是不可能的,每次計算可能需要幾秒鐘,因為它的distinct有千萬級。之前的系統使用了HypoLogLog技術模糊去重后再count distinct,數據新鮮度比較好,但結果是不精確的。
使用StarRocks替換Flink系統后,資源成本和維護成本都減少了很多。優化方案是使用StarRocks做兩層物化視圖:
第一層在明細數據上按照城市、時間做增量聚合,可以用bitmap技術和物化視圖增量更新技術,先聚合成城市粒度、分鐘級的數據。
第二層用物化視圖做面向ODS的分鐘級刷新視圖,因為有幾十個看板,所以視圖非常多,分鐘級刷新是能夠比較好地權衡數據新鮮度和資源使用。
這些看板的SQL不方便修改,所以還用了物化視圖的透明加速能力,自動改寫替換掉它這個報表中的一些SQL。因為第一層已經做了增量聚合,所以第二層計算量比較小,不需要做非常重的聚合計算,只需要把物化視圖的結果做一些簡單的過濾就可以返回了。
StarRocks權衡了數據新鮮度和性能,現在100并發時latency 大概由3秒縮減到了30毫秒,并且實現了精確的1分鐘新鮮度的count distinct。
三、MV for LakeHouse
物化視圖相關的技術,包括構建外表物化視圖、分區關系維護、自動刷新、改寫SQL等等,都可以和數據湖整合起來,使得在外表的場景能夠用物化視圖加速。其中外表的查詢改寫和內表還是有一些差異的,比如Hive可能聲明一些外鍵約束、唯一鍵約束,在查詢改寫過程中是需要這些信息的,我們可以用其它一些方式把這些信息透傳過來,然后就能在優化期器中用于查詢改寫。這幾個技術結合起來實現了比較好的查詢加速效果。
數據湖的架構往往是比較復雜的,接下來看幾個案例。
案例1: 分層建模
分層建模分為以下四層:
ODS層可以是數據湖外表,存儲歷史數據。
DWD層使用外表物化視圖把數據清洗后放到StarRocks內部存儲,以及用PK表可以實時地把TP等數據同步進來,可以用來存儲實時數據。
DWS層用了物化視圖和邏輯視圖兩種技術,物化視圖把結果給物化下來用于加速查詢,邏輯視圖仍然可以訪問實時數據用于簡化業務邏輯,把這兩種技術結合起來就可以面向不同的業務場景、實現不同的效果。
ADS層用邏輯視圖把很多的業務數據給union起來,以及做一些更面向業務的表達。
這樣分層后相對更加靈活,實現了近實時的實時性。存儲也比較開放,歷史數據仍然可以存在數據湖中。中間的數據刷新部分也不用維護,而且仍然可以用其他的查詢引擎。
案例2:實時數據湖
嚴格來說,實時數據湖并不是一個產品或者一個Feature,而是一種解決方案。目前 StarRocks 會結合 Iceberg 以及一些其他Feature,去實現LakeHouse 場景的實時聚合、實時更新,實現整體的解決方案。
實時聚合:主要面向immutable的數據,這類數據可以直接去寫Lake,使用Iceberg這種數據湖的寫入吞吐量會比較高。
實時更新:主要面向mutable的數據,數據湖目前還沒有較好的實時更新能力,StarRocks primary key則可以很好的支持,所以首先會把數據寫到pk表,定時下沉到Lake中,同時在此之上,可以用物化視圖做實時的增量聚合。
結合實時聚合和實時更新兩種場景,把全量數據存在Iceberg中,把聚合、更新數據放在StarRocks中,然后在上層構建物化視圖去做面向業務的加工寬表、聚合結果,可以帶來以下幾方面的業務價值:
- 一是SSOT,不管是面向歸檔,還是面向其它查詢引擎,都能直接查詢數據湖,不會被封閉在一個系統里。
- 二是變成實時后,可以分攤資源,不會在凌晨出現一個業務高峰,而白天又很空閑,導致資源浪費。
- 三是可以發揮不同存儲引擎的優勢,StarRocks支持實時聚合、實時更新,數據湖可以存儲歷史數據,具有超高的寫入吞吐量的優勢。
四、總結展望
StarRocks 后續有幾個發展方向:
第一個是利用云原生架構更好地管理資源,在接入數據湖并構建很多ETL workload之后,如何把各種資源統一管控起來,將會是一個很大的挑戰。
第二個是支持更多的ETL的場景,物化視圖目前還不能解決全部ETL場景,無法徹底替換Flink,所以未來會開發更多的ETL的feature,更好地把ETL場景統一起來。
第三個是進一步加強實時鏈路,會針對數據攝取和數據實時計算等場景開發更多的feature,讓導入各種實時系統的數據變得更加容易,會支持更多的增量計算場景,而不僅僅是實時聚合。
五、問答
問:物化視圖底層存儲也是用三副本嗎?
答:對。物化視圖也是按照表來存儲的,不同于普通表的是會自動維護。Base表跟物化視圖表的存儲都取決存儲引擎,可以設置3副本,可以設置2副本,也可設置1副本,也可以用云原生架構做存算分離,是非常靈活的,關鍵在于如何維護這個base表跟計算結果的映射關系。