作者:StarRocks Committer 李雪巖,國(guó)雙科技技術(shù)架構(gòu)師、StarRocks Active Contributor 龔磊(本文為作者在 StarRocks Summit Asia 2022 上的分享)
本文先介紹物化視圖的一些需求分析,看看現(xiàn)在的物化視圖哪些地方做得好、哪些地方做得不好,然后再針對(duì)這些需求進(jìn)行設(shè)計(jì)。然后再講一下具體的實(shí)現(xiàn)原理,最后再講一下 StarRocks 2.5 版本的物化視圖還會(huì)開(kāi)發(fā)哪些功能。
01、物化視圖的需求分析
1什么是物化視圖
要了解物化視圖可以先了解視圖的概念。視圖是一個(gè)虛擬表(也可以認(rèn)為是一條語(yǔ)句),基于它創(chuàng)建時(shí)指定的查詢(xún)語(yǔ)句返回的結(jié)果集。而物化視圖則是將這個(gè)虛擬表進(jìn)行實(shí)體化,其本身可以理解為是一個(gè)特殊的表。
2物化視圖的應(yīng)用場(chǎng)景
物化視圖最常見(jiàn)的場(chǎng)景是,由基礎(chǔ)的 Base 表通過(guò)創(chuàng)建物化視圖的 SQL 生成物化視圖,當(dāng)用戶(hù)查詢(xún)相似的 SQL 時(shí),查詢(xún)優(yōu)化器可以自動(dòng) QueryRewrite 復(fù)用物化視圖,從而達(dá)到查詢(xún)加速的效果。
在 2.4 之前,我們僅支持的是單表同步的物化視圖,但它缺乏一些復(fù)雜場(chǎng)景的支持,例如只能支持一些簡(jiǎn)單的 SQL。
對(duì)于一個(gè)實(shí)時(shí)的場(chǎng)景,比如用戶(hù)有兩張實(shí)時(shí)表進(jìn)行 Join 操作,由于單表同步物化視圖不支持多表 Join 操作,這種場(chǎng)景就無(wú)法支持了。
對(duì)于離線(xiàn)多表加速建模的場(chǎng)景,通常需要事實(shí)表和維度表的 Join 的操作。這里面有兩方面的需求,一方面是加速的需求,希望我們?cè)诓檫@些 Base 表時(shí)通過(guò) QueryRewrite 加速查詢(xún);另一方面是建模的需求,希望物化視圖能夠屏蔽后面的事實(shí)表和維度表,也就是說(shuō)希望物化視圖可以直接進(jìn)行查詢(xún)。
還有一類(lèi)場(chǎng)景,這類(lèi)場(chǎng)景雖然也可以支持,但是支持得不是很好,就是當(dāng)物化視圖的計(jì)算結(jié)果比較少的時(shí)候,希望分區(qū)分桶比較少,這樣查詢(xún)性能才會(huì)比較好。之前同步的模型,物化視圖與 Base 表是一對(duì)一的關(guān)系,可能就會(huì)出現(xiàn)創(chuàng)建物化視圖雖然結(jié)果很少,但是分區(qū)分桶很多,反而出現(xiàn)查詢(xún)性能下降的現(xiàn)象。
根據(jù)這些場(chǎng)景和問(wèn)題,接下來(lái)我們看看可以怎么去解決這些問(wèn)題。
02、物化視圖的設(shè)計(jì)
1同步解決方案
我們觀察到 SQL 復(fù)雜度越低,數(shù)據(jù)的同步性越好做,當(dāng) SQL 復(fù)雜度越高,數(shù)據(jù)的同步性越來(lái)越難做。之前的同步物化視圖,其實(shí)是選擇了同步性最佳的點(diǎn),但它的弊端就是 SQL 很復(fù)雜的時(shí)候很難做。但是用戶(hù)的大部分場(chǎng)景 SQL 可能是很復(fù)雜的,并且可以接受一定的異步延遲,所以可以犧牲一定的同步性,滿(mǎn)足復(fù)雜 SQL 加速的場(chǎng)景。于是就有了異步刷新的解決方案。
2異步刷新的解決方案
首先我們看看怎么解決之前的實(shí)時(shí)場(chǎng)景的問(wèn)題。在我們使用新版創(chuàng)建物化視圖時(shí),可以通過(guò) PARTITION BY 關(guān)鍵字來(lái)指定物化視圖跟某一個(gè) Base 表的一個(gè)分區(qū)進(jìn)行綁定,當(dāng)前的版本分桶是必填的,但是分桶是可以靈活變化的,然后還可以指定刷新的起始時(shí)間點(diǎn)和間隔。
我們創(chuàng)建物化視圖語(yǔ)句里面的 Query 語(yǔ)句本身是基本沒(méi)有任何限制的,可以寫(xiě)得很復(fù)雜,只要是可以查詢(xún)的基本都可行。對(duì)于實(shí)時(shí)的場(chǎng)景,它其實(shí)是只刷新某一個(gè)分區(qū)的小部分?jǐn)?shù)據(jù)量。對(duì)于實(shí)時(shí)表,導(dǎo)入非常頻繁的,用戶(hù)可以接受分鐘級(jí)刷新的場(chǎng)景下,用戶(hù)可以使用周期性刷新,例如每 1 分鐘刷新一次,這樣可以避免刷新頻率過(guò)高導(dǎo)致物化視圖刷新觸發(fā)過(guò)于頻繁。
然后我們?cè)倏纯措x線(xiàn)的場(chǎng)景,離線(xiàn)場(chǎng)景 Base 表,通常事時(shí)表基本上只有每天才會(huì)去刷新某一個(gè)分區(qū),維表會(huì)全量刷新一個(gè)分區(qū)。這里我們?cè)趧?chuàng)建物化視圖時(shí),可以指定 REFRESH ASYNC,當(dāng)每個(gè) Base 表有數(shù)據(jù)變化的時(shí)候,它會(huì)自動(dòng)去判定哪些分區(qū)需要刷新并進(jìn)行智能刷新,對(duì)于不需要刷新的分區(qū)就不刷新。離線(xiàn)場(chǎng)景也可以支持以天為周期進(jìn)行調(diào)度。離線(xiàn)的場(chǎng)景下由于數(shù)據(jù)量比較大,有可能查詢(xún)需要調(diào)整一些特殊的 Session Variable 參數(shù)才能夠刷新成功,這些特殊的參數(shù)可以通過(guò) Query 里面的 SELECT hint 來(lái)傳入。
但是物化視圖其是一個(gè)需要長(zhǎng)期打磨的功能。周期性刷新和觸發(fā)式刷新覆蓋不了所有的場(chǎng)景,有可能用戶(hù)在不需要刷新的時(shí)候,還花費(fèi)了很多刷新的成本。所以我們提供了一個(gè)手動(dòng)刷新的功能,讓用戶(hù)能靈活地控制刷新的時(shí)機(jī),也就是通過(guò)指定 REFRESH MANUAL。等到物化視圖在后面的版本越來(lái)越完善的時(shí)候,使用手動(dòng)刷新的情況會(huì)漸漸較少。
另外之前還提到了分區(qū)分桶浪費(fèi)的問(wèn)題,關(guān)于解決這個(gè)問(wèn)題的方法,可以通過(guò)指定PARTITION BY DATE_TRUNC(“month”, dt),這樣我們就可以把 dt 這一列本來(lái)按天的 Base 表上卷到按月分區(qū)的表,從而來(lái)減少分區(qū)浪費(fèi)的問(wèn)題。同時(shí)我們也可以指定 Bucket 的數(shù)量,而不是跟 Base 表保持一致。這樣在物化視圖的結(jié)果很少的情況下,我們可以靈活減少分區(qū)和分桶,從而提高查詢(xún)性能,避免分區(qū)分桶的浪費(fèi)。
以上講的這些都是 StarRocks 2.4 已經(jīng)實(shí)現(xiàn)的功能,這些功能是 StarRocks 和社區(qū)共同討論并實(shí)現(xiàn)的。在這里要感謝社區(qū)的小伙伴們。
03、物化視圖的實(shí)現(xiàn)原理
先來(lái)了解一下多表物化視圖的框架,即數(shù)據(jù)模型。在早期的版本中,我們實(shí)際上支持的是單表同步物化視圖,也就是我們基于一個(gè)原始表去創(chuàng)建物化視圖,實(shí)際上物化視圖是以索引的形式去存在的。
在左圖中可以看到表的基礎(chǔ)索引中的 Tablet 和物化視圖索引的 Tablet 是一一對(duì)應(yīng),但是在多表異步的物化視圖的框架中,Tablet 不是一一的對(duì)應(yīng)關(guān)系,物化視圖實(shí)際上是以表的模型去做實(shí)現(xiàn)的。以右圖為例,假設(shè) Base 表有兩個(gè) Partition A 和 B,假設(shè)物化視圖有 Partition C,那么 Partition A、Partition B 的 Tablet 和物化視圖的 Partition C 中的 Tablet 是映射關(guān)系,這種關(guān)系不是一一對(duì)應(yīng)的關(guān)系。
再來(lái)看一下物化視圖的整體框架。我們?cè)谛碌陌姹局兄饕獙?shí)現(xiàn)了多表異步物化視圖,那么就需要一個(gè)異步物化視圖的調(diào)度框架及相應(yīng)的一些實(shí)現(xiàn)邏輯。以上圖舉例,比如在創(chuàng)建物化視圖以及刷新物化視圖的時(shí)候,我們都需要有對(duì)應(yīng)的 Task,以及 TaskRun 執(zhí)行單元去做相應(yīng)的處理。
核心的實(shí)現(xiàn)內(nèi)容實(shí)際上包含以下三方面的技術(shù):Task 調(diào)度框架、分區(qū)刷新維護(hù)、Insert Overwrite。Task 調(diào)度框架解決的是物化視圖異步刷新的問(wèn)題,分區(qū)刷新維護(hù)解決的是分區(qū)同步增刪以及刷新的問(wèn)題,Insert Overwrite 是刷新中的核心技術(shù)。
1Task 調(diào)度框架
首先給大家介紹一下 Task 調(diào)度框架。Task 實(shí)際上是一個(gè)可重用的對(duì)象,是任務(wù)的存儲(chǔ)模板。TaskRun 是其中真正的計(jì)算對(duì)象,每一個(gè) TaskRun 都是基于 Task 這個(gè)模板去做實(shí)現(xiàn)的,是計(jì)算的最小單元。可以類(lèi)比成 Java 的 Class,以及 Class 相應(yīng)的一些實(shí)現(xiàn) Object。在 Task 調(diào)度框架中,支持手動(dòng)刷新、觸發(fā)式刷新以及周期性刷新等三種刷新方式。
再來(lái)看調(diào)度框架的核心架構(gòu)。調(diào)度框架包含這幾方面的內(nèi)容,一個(gè)是調(diào)度器,然后是 Task 和 TaskRun,Pending 隊(duì)列、Running 隊(duì)列以及 TaskRun history 集合。以手動(dòng)刷新任務(wù)舉例,首先基于 Task 去創(chuàng)建 TaskRun 對(duì)象,存放在 Pending 隊(duì)列中。調(diào)度器會(huì)取出 Pending 隊(duì)列中的 TaskRun 做相應(yīng)的執(zhí)行,并存放到 Running 隊(duì)列中,同時(shí)會(huì)基于 TaskRun 運(yùn)行的狀態(tài),進(jìn)入到 TaskRun history 集合中。在調(diào)度框架中也有一些參數(shù)可以配置,比如現(xiàn)在我們隊(duì)列長(zhǎng)度默認(rèn)是 500,并發(fā)數(shù)默認(rèn)是 20,TaskRun 默認(rèn)是清除是三天以上的歷史。有了 Task 框架,我們還需要進(jìn)行分區(qū)的刷新維護(hù)。2分區(qū)刷新維護(hù)
在創(chuàng)建物化視圖的時(shí)候,實(shí)際上我們指定了物化視圖跟某一個(gè) Base 表分區(qū)的綁定關(guān)系,刷新框架會(huì)在刷新前增刪分區(qū),以保證物化視圖的分區(qū)大于 Base 表綁定的分區(qū)。以圖中舉例,假設(shè)我們有這樣一個(gè)表,它有三個(gè)分區(qū) A、B、C,物化視圖也有三個(gè)分對(duì)應(yīng)的分區(qū) A、B、C,它們是一一對(duì)應(yīng)關(guān)系。除了這么種 1:1 的映射關(guān)系,實(shí)際上其中還有 1:n、n:1 以及 n:n 的映射關(guān)系。
有了分區(qū)映射關(guān)系,就可以基于分區(qū)的映射關(guān)系去做對(duì)應(yīng)的一些刷新。我們是基于分區(qū)的版本去判斷哪些分區(qū)需要做刷新。以圖上舉例,假設(shè) Base 表有 1、2、3 三個(gè)分區(qū),物化視圖也有 1、2、3 三個(gè)分區(qū),Base 表分區(qū) 1 的版本是 2,物化視圖分區(qū) 1 的版本也是 2,這個(gè)時(shí)候我們是不需要去做刷新的。假設(shè) Base 表的分區(qū) 2 版本是 4,而物化視圖的分區(qū) 2 版本是 3,這個(gè)時(shí)候我們判斷需要去做進(jìn)一步刷新。那么怎么樣去做刷新,實(shí)際上是依靠于我們底層的 Insert Overwrite 技術(shù)。
3Insert Overwrite
相信有很多同學(xué)用過(guò)臨時(shí)分區(qū),實(shí)際上 Insert Overwrite 的原理就是內(nèi)置的這一過(guò)程。通常有三個(gè)步驟,首先創(chuàng)建一個(gè)臨時(shí)分區(qū),然后把數(shù)據(jù)寫(xiě)到臨時(shí)分區(qū),最終將臨時(shí)分區(qū)和目標(biāo)分區(qū)做原子級(jí)別的替換。
那么以上是多表異步物化設(shè)圖的三種核心技術(shù)的實(shí)現(xiàn)原理。除此我們還需要考慮物化視圖失效的問(wèn)題。
當(dāng)用戶(hù)修改 Base 表的結(jié)構(gòu)時(shí),比如刪除了 Base 表的一個(gè)列時(shí),這個(gè)時(shí)候物化視圖可能會(huì)失效。在當(dāng)前的版本中,物化視圖仍然可以查詢(xún),但是它不能夠被刷新。
以上就是物化視圖核心技術(shù)實(shí)現(xiàn)原理。
上述這些都是 2.4 版本已經(jīng)實(shí)現(xiàn)的功能。StarRocks 2.4 版本是一個(gè)預(yù)覽版本,需要通過(guò)設(shè)置 FE 參數(shù) enable_experimental_mv 開(kāi)啟使用。
04、StarRocks 2.5 版本展望
2.4 版本還有三個(gè)比較重要的功能沒(méi)有實(shí)現(xiàn)。一是不支持從外表去創(chuàng)建物化視圖,2.4 的版本只支持在一個(gè)數(shù)據(jù) DB 上去創(chuàng)建物化視圖,并不支持跨 DB 創(chuàng)建物化視圖;二是不支持創(chuàng)建基于物化視圖的物化視圖;三是還不支持最重要的 QueryRewrite 功能。
2.5 版本會(huì)支持物化視圖的查詢(xún)改寫(xiě),支持從外表創(chuàng)建物化視圖,支持從物化視圖創(chuàng)建物化視圖,支持物化視圖 TTL,優(yōu)化刷新效率、增加部分刷新的語(yǔ)法和配置來(lái)應(yīng)對(duì)復(fù)雜的刷新問(wèn)題和各種復(fù)雜場(chǎng)景,大家可以盡請(qǐng)期待。
審核編輯:郭婷
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7002瀏覽量
88941 -
SQL
+關(guān)注
關(guān)注
1文章
762瀏覽量
44117
原文標(biāo)題:多表物化視圖的設(shè)計(jì)與實(shí)現(xiàn)
文章出處:【微信號(hào):OSC開(kāi)源社區(qū),微信公眾號(hào):OSC開(kāi)源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論