ByteHouse案例實踐:某銷售數據平臺如何基于OLAP大幅提升復雜查詢效率?
在現如今激烈的市場競爭中,銷售數據是企業下一步市場決策的重要依據。銷售數據提供了關于市場需求、客戶行為、產品表現等方面的詳細信息。通過深入分析這些數據,企業銷售人員、決策者等可以獲取有關市場趨勢和消費者偏好的寶貴洞察,從而做出更加明智和精準的決策。
某公司的市場份額一直處于快速增長的態勢,為了更好的統一數據口徑、保障數據質量、控制數據權限,企業內部已將分散的銷售數據統一到一套可視化分析平臺中。該平臺之前由開源ClickHouse作為數據分析引擎,但在引入鑒權ACL用于管理數據權限、保障數據安全之后,該平臺出現性能不足、影響用戶體驗的情況。
ByteHouse是火山引擎推出的一款定位為OLAP的分析型數據庫,基于ClickHouse進行架構升級和優化,在復雜查詢層面擁有顯著優勢。該公司引入ByteHouse之后,結合相關銷售場景,對ByteHouse優化器能力點對點優化,實現查詢效率顯著提升,在某些場景下效率提升達到16倍。
本文將從業務痛點、解決方案、優化結果三個方面,詳細拆解該公司銷售數據平臺如何基于ByteHouse復雜查詢能力實現效率提升。
業務背景:銷售數據平臺采用鑒權ACL模式管理數據權限
在該公司內部,銷售人員(數據使用者)、數據分析師、數據工程師(數據維護和提供方)以及公司管理,一直以來都存在以下痛點問題:
- 對于銷售來說,數據范圍難以全平臺對齊,即便是同一個數據集也會存在可見范圍不同的問題;組織變動、負責的客戶頻繁,調整過后則會存在看數問題。
- 對于數據產品經理、數據工程師、數據分析師等數據維護和提供方來說,數據集行權限維護成本高,了解銷售場景中復雜的鑒權邏輯,導致學習成本高。
- 對于公司合規管理來說,數據權限應該得到合理控制,各個銷售能看到的客戶信息應控制在最小范圍內。
為了解決以上問題,該公司的研發團隊單獨把銷售數據的鑒權內聚成新服務,并且引入新的一種查詢鑒權模式 ACL來解決以上問題。
“鑒權 ACL(Access Control List)”通常指用于進行身份鑒別和權限控制的訪問控制列表。鑒權是指驗證用戶或實體的身份和權限,以確定其是否有權訪問特定的資源或執行特定的操作。引入鑒權 ACL之后,能嚴格控制數據訪問權限,確保只有授權人員可查看和操作敏感的銷售數據,還可以根據員工職責精細劃分權限,比如銷售團隊只能訪問自身業務數據,管理層能獲取更全面數據,提升數據使用的合理性和安全性。
- 引入鑒權ACL之前的查詢情況:
- 引入鑒權ACL后:
綠色部分為SQL改動,通過引入子查詢的方式,使用戶無權限數據過濾,保證用戶鑒權最新狀態。
業務痛點:基于ClickHouse難以滿足鑒權ACL下的數據查詢需求
在引入ACL之前,日常銷售分析查詢就非常復雜、查詢量級大。而在SQL加入ACL控制后,采用的是分布式表JOIN,且ACL表子查詢返回結果大,進一步導致集群負載惡化,ClickHouse集群CPU使用率長期打滿,影響用戶體驗。
性能惡化核心原因為ClickHouse社區的Scatter/Gather執行模型缺少shuffle的能力,對于多輪join難以很好支持。
下面用一個簡單的例子說明Scatter/Gather執行模型下join的原理:
兩張分布式表source和to_join(對應local表分別是source_local和to_join_local)數據分布在兩個分片上,如下圖:
- 先設置
distributed_product_mode = 'allow'
,執行join查詢:
- 每個分片節點獨立執行子查詢
SELECT *FROM to_join AS tj
,然后在本地做join,最后在接收查詢的節點(下文用host server指代)上匯總join結果,如下圖所示
- 最終結果如下:
如果分片數目為N,右表表達式的分布式表to_join
在一次join中就會被重復查詢N次,導致效率低下。為了解決該問題,我們采用Global Join
,或者設置distributed_product_mode='global'
,引擎會自動將分布式表的join改寫成Global Join。
Global Join的原理是host server先執行帶分布式表的子查詢,再類似臨時表存在內存中,發送到其他的節點,讓其他節點join的時不用重復查詢該分布式表。這樣的優化方式讓Global Join效率基本可用了,但還存在如下局限性:
- 右表的大小影響join效率,如果右表比較大,join的時候cache missing會非常嚴重,性能很差;
- 不考慮SPILL的情況下(Graceful hash join可以部分緩解這個問題),右表的必須全部在內存中,容易OOM。
- Broadcast右表實現的效率上也有提升空間,比方說右表數據先匯總到host server,再下發到各個節點多了一輪額外的傳輸和序列化反序列化開銷。
- 多表JOIN,不同的join順序對性能影響也很大,ClickHouse并沒有join reorder的能力,依賴用戶手動調優join的表的順序。
解決方案:遷移到ByteHouse提升銷售數據平臺復雜查詢效率
ByteHouse企業版支持優化器和MPP執行模型,可以較好的支持復雜join的場景,并且優化器能力可以進一步提升查詢效率,成為該公司銷售數據平臺從ClickHouse遷移的首選。
優化器是DBMS中一個核心組件,它負責分析查詢語句,并根據表的結構、索引等信息來生成最優的執行計劃。通過優化查詢執行計劃,可以提高查詢的執行效率,減少資源消耗,提升系統性能。為了提升在復雜場景的查詢性能,ByteHouse 的自研優化器進行了大量的優化,主要包括四個大的優化方向:RBO(基于規則的優化能力),CBO(基于代價的優化能力),分布式計劃優化以及一些高階優化能力。
優化器和MPP執行模型原理
開啟優化器后,執行模式由原來的Scatter/Gather模型切成了完全MPP模型。整個SQL的執行流程如下圖所示(以3節點的集群為例)
- PlanSegment:分布式執行計劃邏輯單元(QueryPlan+Exchange輸入輸出)
- Optimizer: 根據Rule(RBO)和統計信息(CBO)進行查詢計劃的優化,生成最終的查詢計劃PlanSegmentTree.
- Scheduler: 發送PlanSegment到各個Worker
- Exchange:在Pipeline之間傳輸數據
- PipelineExecutor: 驅動執行PlanSegment
ByteHouse優化器四大優化方向
下面用上一節的例子簡單說明:采用之前的SQL
可以看到右表讀取完之后通過exchange進行了廣播到左表再join(不同于原來模式需要先在host server匯總右表再下發到各個節點)。
如果兩個表很大,開啟統計信息的情況下,計劃如下:
左右表會先shuffle N份(N默認為分片總數/10,可以通過distributed_max_parallel_size參數控制)再進行join,這樣單個節點join的時候右表的大小平均是總右表的1/N,內存占用和性能都有很大提升。
開啟ByteHouse優化器后,查詢計劃會有這四類優化:
優化一:RBO:
基于規則的優化能力。支持列裁剪,分區裁剪,表達式簡化,子查詢解關聯,謂詞下推,冗余算子消除,外部連接轉內部連接,算子下推存儲,分布式算子拆分等常見的啟發式優化能力。
- 解關聯
很多OLAP引擎不支持相關子查詢,在語法分析階段就會報錯。優化器實現了完整的解關聯能力,對于關聯查詢可以轉換為常見的 join agg filter 等算子執行,下圖就是一個簡單的解關聯例子。對于一些特殊類型的關聯查詢也可以利用 window 算子執行,更加快速簡潔。
- 非等值Join優化
在很多引擎中,帶有非等值條件的 join 需要通過多個算子來組合執行(inner join + filter + group-by
),而在 ByteHouse 中,支持非等值 join 之后可以直接在 join 算子中完成非等值條件的執行。
優化器會對一些關聯子查詢轉成非等值 join 來執行,相較于轉成其他常見的算子(inner join, filter, agg)性能有一倍以上的提升。
優化二:CBO
基于代價的優化能力。基于級聯搜索框架,利用Graph分區技術實現了高效的Join枚舉算法,以及基于直方圖的代價估算,對10表級別規模的Join Reorder問題,能夠全量枚舉并尋求最優解,同時針對于10表規模的Join Reorder支持啟發式枚舉并尋求最優解。CBO支持基于規程擴展搜索空間,除了常見的Join Reorder問題以外,還支持外部Join/Join Reorder、Aggregate/Join Reorder、Magic Set Placement等相關優化能力。
優化三:分布式計劃優化
業界主流實現分為兩個階段,首先尋求最優的單機版計劃,然后將其分布式化。但是這樣的設計流程,不能提前考慮分布式系統的特點,可能會導致網絡延遲、數據分布不均衡,并導致可擴展性限制等問題。我們的方案則是將這兩個階段融合在一起,在整個 CBO 尋求最優解的過程中,會結合分布式計劃的訴求,從代價的角度選擇最優的分布式計劃,同時在 Join/Aggregate 過程中,也支持 Partition 屬性展開。
另外,我們也在 CBO 中實現了對于 Aggregate/Join Reorder,Magic Set Placement 等相關能力。對于 CTE 的實現方式也基于 Cost 進行選擇,在 inline,shared 和 partial inline 之間做權衡,選出最優的計劃。在 tpcds 等 benchmark 中都有一定的應用。
優化四:高階優化能力
ByteHouse實現了動態Filter下推、物化視圖改寫、基于代價的CTE(公共表達式共享)、計劃復用、結果復用等高階優化能力。
最佳實踐之“聚合計算加速”
在數據庫中,優化器對于聚合計算加速起著關鍵作用。優化器能夠分析查詢語句的結構和涉及的數據,評估不同的執行計劃。對于聚合計算,它會考慮數據的分布、索引的可用性以及表之間的關系等因素。除了JOIN場景,ByteHouse在聚合計算場景也產生了積極的影響。
- 多節點并行merge聚合結果
分散/聚集模式在聚集階段會聚合各個節點局部聚合的中間結果,這時容易遇到單節點的性能和內存瓶頸,其典型的場景是大數據的count distinct
。開啟ByteHouse優化器后,我們可以使用10%的分片(通過distributed_max_parallel_size參數調整,最大值為集群分片數目)來做最終的聚合操作,實現較好的并行聚合。
- 優化器會對聚合進行改寫優化,提升聚合性能
如果缺少group by key的聚合操作,在沒開優化器的情況下,Gather階段在單機內為單線程聚合(由于缺少group by key無法并行)。ByteHouse優化器能實現進行自動改寫,除了多節點并行合并聚合結果,單節點內部也能并行。
下面為tpch
的數據(6億數據的lineitem表)在一個兩節點集群測試(最后merge的節點為同一個),SQL如下:
開啟優化器耗時從5.913秒下降到了2.263秒。
優化結果:最高16倍,相關場景查詢效率提升
通過非ACL查詢和ACL查詢兩個方向,我們可以看到查詢時間在優化前后有顯著提升。其中,在ACL查詢中的60M廣告客戶DI場景中,引入ByteHouse之后將查詢效率從16s縮短為秒級,提升了16倍。
- 非ACL查詢
?
抽取該公司銷售平臺某數據集測試
?
- ACL查詢
?
抽取該公司銷售平臺某數據集測試
?
總結來看,但隨著用戶使用場景愈加復雜,ByteHouse針對復雜的查詢場景,在RBO、CBO、分布式計劃等層面進行大量優化,進一步提升了OLAP在各個場景下的查詢性能。未來,ByteHouse也將持續為更多企業的數據分析能力提供支持,助推數智化轉型升級。