ByteHouse案例實踐:某銷售數(shù)據(jù)平臺如何基于OLAP大幅提升復(fù)雜查詢效率?
更多技術(shù)交流、求職機會,歡迎關(guān)注字節(jié)跳動數(shù)據(jù)平臺微信公眾號,回復(fù)【1】進入官方交流群
在現(xiàn)如今激烈的市場競爭中,銷售數(shù)據(jù)是企業(yè)下一步市場決策的重要依據(jù)。銷售數(shù)據(jù)提供了關(guān)于市場需求、客戶行為、產(chǎn)品表現(xiàn)等方面的詳細(xì)信息。通過深入分析這些數(shù)據(jù),企業(yè)銷售人員、決策者等可以獲取有關(guān)市場趨勢和消費者偏好的寶貴洞察,從而做出更加明智和精準(zhǔn)的決策。
某公司的市場份額一直處于快速增長的態(tài)勢,為了更好的統(tǒng)一數(shù)據(jù)口徑、保障數(shù)據(jù)質(zhì)量、控制數(shù)據(jù)權(quán)限,企業(yè)內(nèi)部已將分散的銷售數(shù)據(jù)統(tǒng)一到一套可視化分析平臺中。該平臺之前由開源ClickHouse作為數(shù)據(jù)分析引擎,但在引入鑒權(quán)ACL用于管理數(shù)據(jù)權(quán)限、保障數(shù)據(jù)安全之后,該平臺出現(xiàn)性能不足、影響用戶體驗的情況。
ByteHouse是火山引擎推出的一款定位為OLAP的分析型數(shù)據(jù)庫,基于ClickHouse進行架構(gòu)升級和優(yōu)化,在復(fù)雜查詢層面擁有顯著優(yōu)勢。該公司引入ByteHouse之后,結(jié)合相關(guān)銷售場景,對ByteHouse優(yōu)化器能力點對點優(yōu)化,實現(xiàn)查詢效率顯著提升,在某些場景下效率提升達(dá)到16倍。
本文將從業(yè)務(wù)痛點、解決方案、優(yōu)化結(jié)果三個方面,詳細(xì)拆解該公司銷售數(shù)據(jù)平臺如何基于ByteHouse復(fù)雜查詢能力實現(xiàn)效率提升。
業(yè)務(wù)背景:銷售數(shù)據(jù)平臺采用鑒權(quán)ACL模式管理數(shù)據(jù)權(quán)限
在該公司內(nèi)部,銷售人員(數(shù)據(jù)使用者)、數(shù)據(jù)分析師、數(shù)據(jù)工程師(數(shù)據(jù)維護和提供方)以及公司管理,一直以來都存在以下痛點問題:
- 對于銷售來說,數(shù)據(jù)范圍難以全平臺對齊,即便是同一個數(shù)據(jù)集也會存在可見范圍不同的問題;組織變動、負(fù)責(zé)的客戶頻繁,調(diào)整過后則會存在看數(shù)問題。
- 對于數(shù)據(jù)產(chǎn)品經(jīng)理、數(shù)據(jù)工程師、數(shù)據(jù)分析師等數(shù)據(jù)維護和提供方來說,數(shù)據(jù)集行權(quán)限維護成本高,了解銷售場景中復(fù)雜的鑒權(quán)邏輯,導(dǎo)致學(xué)習(xí)成本高。
- 對于公司合規(guī)管理來說,數(shù)據(jù)權(quán)限應(yīng)該得到合理控制,各個銷售能看到的客戶信息應(yīng)控制在最小范圍內(nèi)。
為了解決以上問題,該公司的研發(fā)團隊單獨把銷售數(shù)據(jù)的鑒權(quán)內(nèi)聚成新服務(wù),并且引入新的一種查詢鑒權(quán)模式 ACL來解決以上問題。
“鑒權(quán) ACL(Access Control List)”通常指用于進行身份鑒別和權(quán)限控制的訪問控制列表。鑒權(quán)是指驗證用戶或?qū)嶓w的身份和權(quán)限,以確定其是否有權(quán)訪問特定的資源或執(zhí)行特定的操作。引入鑒權(quán) ACL之后,能嚴(yán)格控制數(shù)據(jù)訪問權(quán)限,確保只有授權(quán)人員可查看和操作敏感的銷售數(shù)據(jù),還可以根據(jù)員工職責(zé)精細(xì)劃分權(quán)限,比如銷售團隊只能訪問自身業(yè)務(wù)數(shù)據(jù),管理層能獲取更全面數(shù)據(jù),提升數(shù)據(jù)使用的合理性和安全性。
- 引入鑒權(quán)ACL之前的查詢情況:
- 引入鑒權(quán)ACL后:
綠色部分為SQL改動,通過引入子查詢的方式,使用戶無權(quán)限數(shù)據(jù)過濾,保證用戶鑒權(quán)最新狀態(tài)。


業(yè)務(wù)痛點:基于ClickHouse難以滿足鑒權(quán)ACL下的數(shù)據(jù)查詢需求
在引入ACL之前,日常銷售分析查詢就非常復(fù)雜、查詢量級大。而在SQL加入ACL控制后,采用的是分布式表JOIN,且ACL表子查詢返回結(jié)果大,進一步導(dǎo)致集群負(fù)載惡化,ClickHouse集群CPU使用率長期打滿,影響用戶體驗。
性能惡化核心原因為ClickHouse社區(qū)的Scatter/Gather執(zhí)行模型缺少shuffle的能力,對于多輪join難以很好支持。
下面用一個簡單的例子說明Scatter/Gather執(zhí)行模型下join的原理:
兩張分布式表source和to_join(對應(yīng)local表分別是source_local和to_join_local)數(shù)據(jù)分布在兩個分片上,如下圖:

- 先設(shè)置
distributed_product_mode = 'allow',執(zhí)行join查詢:

- 每個分片節(jié)點獨立執(zhí)行子查詢
SELECT *FROM to_join AS tj,然后在本地做join,最后在接收查詢的節(jié)點(下文用host server指代)上匯總join結(jié)果,如下圖所示

- 最終結(jié)果如下:

如果分片數(shù)目為N,右表表達(dá)式的分布式表
to_join在一次join中就會被重復(fù)查詢N次,導(dǎo)致效率低下。為了解決該問題,我們采用Global Join,或者設(shè)置distributed_product_mode='global',引擎會自動將分布式表的join改寫成Global Join。
Global Join的原理是host server先執(zhí)行帶分布式表的子查詢,再類似臨時表存在內(nèi)存中,發(fā)送到其他的節(jié)點,讓其他節(jié)點join的時不用重復(fù)查詢該分布式表。這樣的優(yōu)化方式讓Global Join效率基本可用了,但還存在如下局限性:
- 右表的大小影響join效率,如果右表比較大,join的時候cache missing會非常嚴(yán)重,性能很差;
- 不考慮SPILL的情況下(Graceful hash join可以部分緩解這個問題),右表的必須全部在內(nèi)存中,容易OOM。
- Broadcast右表實現(xiàn)的效率上也有提升空間,比方說右表數(shù)據(jù)先匯總到host server,再下發(fā)到各個節(jié)點多了一輪額外的傳輸和序列化反序列化開銷。
- 多表JOIN,不同的join順序?qū)π阅苡绊懸埠艽螅珻lickHouse并沒有join reorder的能力,依賴用戶手動調(diào)優(yōu)join的表的順序。
解決方案:遷移到ByteHouse提升銷售數(shù)據(jù)平臺復(fù)雜查詢效率
ByteHouse企業(yè)版支持優(yōu)化器和MPP執(zhí)行模型,可以較好的支持復(fù)雜join的場景,并且優(yōu)化器能力可以進一步提升查詢效率,成為該公司銷售數(shù)據(jù)平臺從ClickHouse遷移的首選。
優(yōu)化器是DBMS中一個核心組件,它負(fù)責(zé)分析查詢語句,并根據(jù)表的結(jié)構(gòu)、索引等信息來生成最優(yōu)的執(zhí)行計劃。通過優(yōu)化查詢執(zhí)行計劃,可以提高查詢的執(zhí)行效率,減少資源消耗,提升系統(tǒng)性能。為了提升在復(fù)雜場景的查詢性能,ByteHouse 的自研優(yōu)化器進行了大量的優(yōu)化,主要包括四個大的優(yōu)化方向:RBO(基于規(guī)則的優(yōu)化能力),CBO(基于代價的優(yōu)化能力),分布式計劃優(yōu)化以及一些高階優(yōu)化能力。
優(yōu)化器和MPP執(zhí)行模型原理
開啟優(yōu)化器后,執(zhí)行模式由原來的Scatter/Gather模型切成了完全MPP模型。整個SQL的執(zhí)行流程如下圖所示(以3節(jié)點的集群為例)

- PlanSegment:分布式執(zhí)行計劃邏輯單元(QueryPlan+Exchange輸入輸出)
- Optimizer: 根據(jù)Rule(RBO)和統(tǒng)計信息(CBO)進行查詢計劃的優(yōu)化,生成最終的查詢計劃PlanSegmentTree. Query Optimizer User Guide
- Scheduler: 發(fā)送PlanSegment到各個Worker
- Exchange:在Pipeline之間傳輸數(shù)據(jù)
- PipelineExecutor: 驅(qū)動執(zhí)行PlanSegment
ByteHouse優(yōu)化器四大優(yōu)化方向
下面用上一節(jié)的例子簡單說明:采用之前的SQL

可以看到右表讀取完之后通過exchange進行了廣播到左表再join(不同于原來模式需要先在host server匯總右表再下發(fā)到各個節(jié)點)。
如果兩個表很大,開啟統(tǒng)計信息的情況下,計劃如下:

左右表會先shuffle N份(N默認(rèn)為分片總數(shù)/10,可以通過distributed_max_parallel_size參數(shù)控制)再進行join,這樣單個節(jié)點join的時候右表的大小平均是總右表的1/N,內(nèi)存占用和性能都有很大提升。
開啟ByteHouse優(yōu)化器后,查詢計劃會有這四類優(yōu)化:
優(yōu)化一:RBO:
基于規(guī)則的優(yōu)化能力。支持列裁剪,分區(qū)裁剪,表達(dá)式簡化,子查詢解關(guān)聯(lián),謂詞下推,冗余算子消除,外部連接轉(zhuǎn)內(nèi)部連接,算子下推存儲,分布式算子拆分等常見的啟發(fā)式優(yōu)化能力。
- 解關(guān)聯(lián)
很多OLAP引擎不支持相關(guān)子查詢,在語法分析階段就會報錯。優(yōu)化器實現(xiàn)了完整的解關(guān)聯(lián)能力,對于關(guān)聯(lián)查詢可以轉(zhuǎn)換為常見的 join agg filter 等算子執(zhí)行,下圖就是一個簡單的解關(guān)聯(lián)例子。對于一些特殊類型的關(guān)聯(lián)查詢也可以利用 window 算子執(zhí)行,更加快速簡潔。

- 非等值Join優(yōu)化
在很多引擎中,帶有非等值條件的 join 需要通過多個算子來組合執(zhí)行(
inner join + filter + group-by),而在 ByteHouse 中,支持非等值 join 之后可以直接在 join 算子中完成非等值條件的執(zhí)行。優(yōu)化器會對一些關(guān)聯(lián)子查詢轉(zhuǎn)成非等值 join 來執(zhí)行,相較于轉(zhuǎn)成其他常見的算子(inner join, filter, agg)性能有一倍以上的提升。
優(yōu)化二:CBO
基于代價的優(yōu)化能力?;诩壜?lián)搜索框架,利用Graph分區(qū)技術(shù)實現(xiàn)了高效的Join枚舉算法,以及基于直方圖的代價估算,對10表級別規(guī)模的Join Reorder問題,能夠全量枚舉并尋求最優(yōu)解,同時針對于10表規(guī)模的Join Reorder支持啟發(fā)式枚舉并尋求最優(yōu)解。CBO支持基于規(guī)程擴展搜索空間,除了常見的Join Reorder問題以外,還支持外部Join/Join Reorder、Aggregate/Join Reorder、Magic Set Placement等相關(guān)優(yōu)化能力。
優(yōu)化三:分布式計劃優(yōu)化
業(yè)界主流實現(xiàn)分為兩個階段,首先尋求最優(yōu)的單機版計劃,然后將其分布式化。但是這樣的設(shè)計流程,不能提前考慮分布式系統(tǒng)的特點,可能會導(dǎo)致網(wǎng)絡(luò)延遲、數(shù)據(jù)分布不均衡,并導(dǎo)致可擴展性限制等問題。我們的方案則是將這兩個階段融合在一起,在整個 CBO 尋求最優(yōu)解的過程中,會結(jié)合分布式計劃的訴求,從代價的角度選擇最優(yōu)的分布式計劃,同時在 Join/Aggregate 過程中,也支持 Partition 屬性展開。
另外,我們也在 CBO 中實現(xiàn)了對于 Aggregate/Join Reorder,Magic Set Placement 等相關(guān)能力。對于 CTE 的實現(xiàn)方式也基于 Cost 進行選擇,在 inline,shared 和 partial inline 之間做權(quán)衡,選出最優(yōu)的計劃。在 tpcds 等 benchmark 中都有一定的應(yīng)用。
優(yōu)化四:高階優(yōu)化能力
ByteHouse實現(xiàn)了動態(tài)Filter下推、物化視圖改寫、基于代價的CTE(公共表達(dá)式共享)、計劃復(fù)用、結(jié)果復(fù)用等高階優(yōu)化能力。
最佳實踐之“聚合計算加速”
在數(shù)據(jù)庫中,優(yōu)化器對于聚合計算加速起著關(guān)鍵作用。優(yōu)化器能夠分析查詢語句的結(jié)構(gòu)和涉及的數(shù)據(jù),評估不同的執(zhí)行計劃。對于聚合計算,它會考慮數(shù)據(jù)的分布、索引的可用性以及表之間的關(guān)系等因素。除了JOIN場景,ByteHouse在聚合計算場景也產(chǎn)生了積極的影響。
- 多節(jié)點并行merge聚合結(jié)果
分散/聚集模式在聚集階段會聚合各個節(jié)點局部聚合的中間結(jié)果,這時容易遇到單節(jié)點的性能和內(nèi)存瓶頸,其典型的場景是大數(shù)據(jù)的
count distinct。開啟ByteHouse優(yōu)化器后,我們可以使用10%的分片(通過distributed_max_parallel_size參數(shù)調(diào)整,最大值為集群分片數(shù)目)來做最終的聚合操作,實現(xiàn)較好的并行聚合。- 優(yōu)化器會對聚合進行改寫優(yōu)化,提升聚合性能
如果缺少group by key的聚合操作,在沒開優(yōu)化器的情況下,Gather階段在單機內(nèi)為單線程聚合(由于缺少group by key無法并行)。ByteHouse優(yōu)化器能實現(xiàn)進行自動改寫,除了多節(jié)點并行合并聚合結(jié)果,單節(jié)點內(nèi)部也能并行。
下面為
tpch的數(shù)據(jù)(6億數(shù)據(jù)的lineitem表)在一個兩節(jié)點集群測試(最后merge的節(jié)點為同一個),SQL如下:
開啟優(yōu)化器耗時從5.913秒下降到了2.263秒。
優(yōu)化結(jié)果:最高16倍,相關(guān)場景查詢效率提升
通過非ACL查詢和ACL查詢兩個方向,我們可以看到查詢時間在優(yōu)化前后有顯著提升。其中,在ACL查詢中的60M廣告客戶DI場景中,引入ByteHouse之后將查詢效率從16s縮短為秒級,提升了16倍。
- 非ACL查詢
抽取該公司銷售平臺某數(shù)據(jù)集測試

- ACL查詢
抽取該公司銷售平臺某數(shù)據(jù)集測試

總結(jié)來看,但隨著用戶使用場景愈加復(fù)雜,ByteHouse針對復(fù)雜的查詢場景,在RBO、CBO、分布式計劃等層面進行大量優(yōu)化,進一步提升了OLAP在各個場景下的查詢性能。未來,ByteHouse也將持續(xù)為更多企業(yè)的數(shù)據(jù)分析能力提供支持,助推數(shù)智化轉(zhuǎn)型升級。
點擊跳轉(zhuǎn) 火山引擎云原生數(shù)倉ByteHouse 了解更多

ByteHouse是火山引擎推出的一款定位為OLAP的分析型數(shù)據(jù)庫,基于ClickHouse進行架構(gòu)升級和優(yōu)化,在復(fù)雜查詢層面擁有顯著優(yōu)勢。
浙公網(wǎng)安備 33010602011771號