作者:李鵬霖(丁典),小紅書-研發工程師,StarRocks Contributor & Apache Impala Committer
本文整理自小紅書工程師在 StarRocks 年度峰會上的分享,介紹了小紅書自助分析平臺中,StarRocks 與 Iceberg 結合后,如何實現極速湖倉分析架構。
與原有架構相比,湖上分析架構的 P90 查詢性能提升了 3 倍,目前查詢 響應時間 穩定在 10 秒以內。 同時,采用 Iceberg 存儲格式后,盡管數據量和行數保持不變,但實際存儲空間相較原有 ClickHouse 存算分離版本減少了一半。
RedBI 自助分析是小紅書數據平臺下的一款可視化、即席查詢分析工具,專為分析師設計。它支持通過簡單的拖拽操作完成數據分析,并在秒級返回查詢結果,核心特點可以總結為: 靈活、快速、自助 。
下圖為自助分析平臺的原始架構,其核心是小紅書內部自研存算分離版本的 ClickHouse。通過存算分離和智能緩存,不僅延長了數據集的生命周期,還能根據業務使用習慣將熱點數據緩存在本地,從而實現接近存算一體架構的查詢性能。
在數據分析流程中,分析師首先與數據倉庫團隊討論數據需求。根據需求,數據倉庫團隊會創建相應的數據集,并在小紅書的大數據研發管理平臺 Dataverse 上開發 Hive2CK 類型的 ETL 任務。
Hive2CK 任務 是一種基于 Spark 的數據處理任務,主要從上游的 Hive 表中獲取數據。處理后的數據會先寫入 OSS(對象存儲服務),然后通過 ClickHouse 將這些文件加載至其系統中,根據用戶的使用習慣將熱點數據緩存至本地,確保最終提供給用戶查詢。
原架構痛點
首先,隨著業務需求的快速增長和分析師使用習慣的不斷變化,最初基于與數據倉庫團隊溝通制定的索引策略逐漸失效,導致數據集的查詢性能出現明顯下降。現有架構沒有靈活的機制來根據分析需求和使用習慣動態調整排序鍵與索引,因此導致 查詢性能下降 。
其次,ClickHouse 在支持 Join 操作方面存在一定限制。盡管可以為部分數據集建立 Colocate Join,但其桶數與集群節點綁定的方式,使得擴容或縮容時,節點數和桶數之間的依賴關系增加了操作復雜度。此外,維度表無法復用,Join Key 的綁定程度過高,使得不同數據集之間的 Join 操作靈活性受限。
最后,數據的訪問方式也存在一定局限。目前的數據訪問只能通過 ClickHouse 查詢,缺乏更靈活的方式,尤其在一些場景下,某些數據需要根據不同的分析需求進行讀取。如果繼續依賴 ClickHouse 來讀取這些數據,可能會對線上服務產生影響,導致系統在處理多樣化需求時,性能和效率遭遇瓶頸。
這些問題不僅影響了查詢性能,也限制了平臺的擴展性和自助性,迫切需要找到一套有效的解決方案來應對當前架構的挑戰。
湖上分析架構
隨著原架構暴露出的性能瓶頸和靈活性限制,我們開始尋求更加高效的解決方案。在此背景下,RedBI 自助分析平臺的架構進行了重大升級,采用了新的湖上分析架構。
首先,原有的 Hive2CK 替換為 Hive2Iceberg,數據存儲格式轉為 Parquet。與 ClickHouse 存儲格式相比,這種轉變不僅在支持各自最優壓縮算法的前提下,實現了更高的壓縮率, 實際應用中的壓縮比提升了近一倍 。此外,StarRocks 作為 OLAP 查詢引擎,具備了出色的擴縮容能力和快速的響應速度。
與此同時,依托 StarRocks 的 DataCache 功能,查詢性能不再依賴于網卡 I/O。通過將熱點數據緩存至本地 BE 節點,避免了頻繁的遠程數據拉取,進一步提升了查詢的穩定性和響應速度。
在年初立項前,我們對湖上分析架構進行了 POC 測試。測試集選取了當時自助分析中排名前十的熱門數據集,并模擬了 N 天內的實際查詢場景。測試結果表明,與原有架構相比, 湖上分析架構的 P90 查詢性能實現了 3 倍的提升。
排序鍵 保鮮能力
為了應對隨著時間推移數據集查詢性能下降的問題,我們設計了一套湖上分析數據集智能優化的解決方案。
-
擴展 StarRocks 的審計日志插件,新增了 Iceberg ScanReport 的關鍵信息(如 nonPartFilterCols、resultDataFiles 和 dataInBytes)。
-
結合審計日志數據與表統計信息,預估用戶的使用習慣,智能選擇排序列。
-
針對新增分區數據,通過異步 ZOrder 排序任務優化非分區列的 DataSkip 效果,從而實現排序鍵和索引的持續優化。
提升數據集的自助性
針對多表分析場景(如自助分析人群包維表和筆記維表),當前,分析平臺采用了 Broadcast Join / InSubQuery 的方式進行處理,這相較于傳統的 Colocate Join 具有顯著的性能優勢。由于 Broadcast Join 不依賴于節點綁定,它使得擴容與縮容變得更加靈活,能夠根據業務需求動態調整,而不受固定節點數的限制。
為了進一步提升數據集的自助性,我們引入了靈活配置的 JoinKey 策略。原則上,只要能夠避免數據傾斜,任何字段都可作為 JoinKey。不過,考慮到當前集群規模與平臺性能要求,我們對可進行 Shuffle Join 的維表數量做出了限制,最多支持與主表進行關聯的 四個維表 ,以避免影響其他數據集的快速響應。
取數靈活
湖上數據集的存儲與查詢完全分離,賦予了更高的靈活性。用戶可以直接通過 SQL 在公共 OLAP 資源池中進行啟發式和探索式查詢,既滿足了多樣化需求,又避免了對特定引擎或集群的依賴。
Data Skipping
-
關于排序的優化:
當我們在 DLF (Data Lake Formation)中檢測到大部分拖拽查詢都集中在某一列時,可以采用 線性排序 來提升效率。而對于兩列或三列的場景,可以進一步考慮多維排序。需要注意的是,排序列通常不會超過三列,這樣既能保證查詢性能,又避免了復雜度過高的問題。
-
Z-Order排序:
Z-Order(也稱為Z-Order Curve)是一種空間填充曲線,用于將多維數據映射到一維數據中。Z-Order 本質上是一種對多維數據進行排序的方式,它通過將多個維度的坐標交替地排列在一起,從而形成一個線性索引。
Z-Order 通過將數據點在多維空間中的坐標進行交替二進制編碼,然后根據這些編碼來排序。例如,在二維空間中,假設一個點有兩個維度(x, y),我們可以將 x 和 y 的二進制位交替排列,形成一個新的值。對于更高維度的數據,Z-Order 會擴展此方法。在二維情況下,如果一個點的坐標是 (x, y),而 x 和 y 的二進制表示分別為:
-
x = 3 → 011
-
y = 5 → 101
那么,Z-Order 會將這兩個二進制值交替取各位形成成:
-
z = 0, 1, 1, 0, 1, 1
Z-Order 的關鍵在于它可以對多維數據進行有效的線性排序,這種排序在某些查詢模式下具有很好的性能表現,尤其是范圍查詢。
-
DataFile ( Parquet file)非分區列 min-max 索引
Iceberg 具備“DataFile(Parquet 文件)非分區列的 Min-Max 索引”功能,具體表現為:
-
無需打開具體的 Parquet 文件,用戶即可通過 Iceberg 元數據訪問該索引。
-
在經過上述排序后,Parquet 文件內部數據將呈現有序結構。結合 Min-Max 索引特性,Iceberg 能在前端(FE)執行謂詞下推,從而顯著提升數據湖分析的性能。
上圖展示了 Iceberg 的整體結構,元數據文件中的 ManifestFile 包含了大量 DataFile 級別的指標,例如:
DataFile.RECORD_COUNT,
DataFile.FILE_SIZE,
DataFile.COLUMN_SIZES,
DataFile.VALUE_COUNTS,
DataFile.NULL_VALUE_COUNTS,
DataFile.NAN_VALUE_COUNTS,
DataFile.LOWER_BOUNDS,
DataFile.UPPER_BOUNDS,
...
有了全部 DataFile 中非分區列的 min-max 索引數據,就可以做謂詞下推。在 OLAP 引擎創建查詢計劃時,通過 org.apache.iceberg.Scan#planFiles 接口,根據 WHERE 子句中的謂詞和 min-max 索引數據進行 DataFiles 級別的過濾,從而顯著提升查詢性能。
參考:
https://github.com/apache/iceberg/blob/main/api/src/main/java/org/apache/iceberg/TableScan.java
https://github.com/apache/iceberg/blob/main/api/src/main/java/org/apache/iceberg/DataFile.java
智能選擇 Z-Order 排序鍵
為解決 ClickHouse 索引鍵保鮮度較低 的問題,我們設計了一種基于用戶行為記錄的智能排序鍵選擇與更新機制,應用于 自助分析平臺 ,并通過 Z-Order 排序 提升查詢效率。上圖紅框展示了這一機制的核心流程。
具體實現步驟如下:
-
StarRocks 審計日志插件: 記錄每個查詢中每個表的下推的非分區列信息,以及 planFiles 接口返回的迭代器中涉及的 DataFiles 總 Bytes 等信息。
-
數據湖管理平臺 (DLF): 通過分析審計日志,智能推斷出自助分析數據集中的表的候選排序列。根據這些列的NDV(不同值數量)做一層篩選,最終系統會自動在 Dataverse 平臺創建和更新rewrite_zorder_dataFiles 任務。
-
Dataverse 平臺 :具有任務血緣能力,確保在上游 hive2iceberg 任務完成后,自動觸發 rewrite_zorder_dataFiles 任務。
-
異步執行: rewrite_zorder_dataFiles 任務的執行是異步的,依賴于 Iceberg 的原子提交(atomiccommit)機制,分析師用戶不感知整個優化過程。
StarRocks x Iceberg JOIN
在自助分析場景中,用戶對數據集自助性的需求不斷提升,尤其是在 JoinKey 靈活選擇 上。StarRocks 支持成熟的 Shuffle Join 和 Broadcast Join 能力,不受分桶數或集群節點擴縮容的影響,能夠快速擴展原數據集的 JoinKey。用戶只需審批通過,即可在 分鐘級 內完成新 JoinKey 的上線配置。
在項目中期階段,湖上數據集的覆蓋率已經達到 50%。然而,由于大多數數據集是從 ClickHouse 遷移而來的單表數據,且當時機型無法滿足 DataCache 的使用需求,分析任務仍依賴從 OSS 讀取 Parquet 文件。這種情況下,隨著用戶需求從單表分析轉向多表數據集配置,Shuffle Join 的使用頻率激增,網卡帶寬逐漸成為性能瓶頸。
為解決這一問題,我們首先針對規模較大的多表數據集,選擇采用 Iceberg 分桶表(10 桶) 的方式優化數據分布。同時,在 StarRocks 中引入對 Iceberg 分桶表的 Colocate Join 和 Bucket Join 支持,減少 Shuffle Join 對網卡帶寬的依賴,從而緩解性能壓力。在這一階段,我們優先緩解網卡帶寬瓶頸,待機型滿足要求后,再逐步引入 DataCache ,通過本地磁盤讀取替代從 OSS 讀取數據的方式。
隨著 DataCache 的引入,網卡帶寬幾乎完全騰出來用于 Shuffle Join 和 Broadcast Join,這不僅提升了性能,也保留了對 JoinKey 的靈活擴展能力。即使在使用分桶表時,仍能夠兼顧 Shuffle Join 的擴展性,無需考慮集群節點數量的問題, 提高數據集自主性 。
排序列選取算法
在數據湖管理平臺中,為提升查詢性能和優化數據存儲結構,排序列的篩選顯得尤為重要。以下是排序列選取算法的具體規則和條件:
-
唯一值數量 (NDV)
排序列的候選字段需要具備足夠的區分度。因此,算法會篩選唯一值數量(NDV)不少于 15 的列,以避免因低區分度而導致的排序效果較差。
-
頻次比例
某列的查詢使用頻率,即列的使用次數與該表的查詢總次數的比值,應不少于 0.15。這一條件確保排序列是用戶查詢的核心字段,有助于優化高頻使用場景。
-
文件數量
數據分區中文件數量的豐富性是影響排序效果的另一個因素。候選列所在的分區,文件數量應超過 10 個,以確保排序后的數據能覆蓋更多文件。
-
頻次排名
為進一步提高排序列的篩選精度,算法優先關注查詢頻次排名前 3 的列。這種方式能夠快速鎖定用戶最常查詢的字段,最大化排序優化的收益。
-
查詢占比
最后,通過分析列在整體查詢中的占比,判斷其是否值得進行排序。如果某列的查詢占比較低,即便符合其他條件,也可能會被排除在排序列之外,從而避免無效優化。
查詢性能優化
Data Skip 效果
隨著業務需求的變化,某流量占比較高的數據集經歷了多輪迭代和擴展。從最初包含店鋪 ID、用戶 ID、商品 ID 等基本字段,到逐步加入直播間 ID 和用戶瀏覽筆記 ID 等信息,該數據集的字段不斷豐富以滿足日益復雜的分析需求。
為了應對這種動態變化,我們通過調整 Z-Order 排序任務中的排序列(sort_order),實現對數據的動態優化。具體來說,根據分析師的使用習慣和 T+1 階段反饋,及時調整排序方式,使得新增數據可以更貼近近期用戶的查詢模式。值得注意的是,這一優化完全異步進行,不會影響歷史數據,用戶也無需感知優化過程即可受益。
優化完成后,該數據集的某些常用查詢模式顯著受益,占整體查詢的比例達到 30%。從優化后的統計圖表可以看到,Data Skip 技術在減少數據掃描量上效果明顯,當前每日掃描數據量與優化后的 Data Skip 數據量形成了鮮明對比。
Data Cache
在數據湖分析場景中,StarRocks作為OLAP查詢引擎,需要高效地掃描存儲在對象存儲(如OSS)中的 Parquet 文件。以小紅書自助分析平臺為例,頻繁訪問相同的數據會導致重復的網絡I/O開銷,尤其是在數據是 T+1 產出時。此時,帶寬資源往往不能充分用于多表數據集的Join操作。為了優化這一問題,StarRocks 自 2.5 版本引入了 DataCache 功能。
StarRocks DataCache 通過將外部存儲系統中的原始數據切分成多個數據塊,并將這些塊緩存到StarRocks本地的BE節點,從而減少了重復的遠程數據拉取開銷。這樣,熱點數據可以被緩存到本地,顯著提升了查詢和分析的性能。根據測試數據, 集群的 P90 查詢性能提升約 20% 。需要注意的是,緩存的塊位置與節點數量緊密相關。當集群進行擴縮容操作時,部分緩存會失效,導致一些數據塊不再有效。
為了解決擴縮容后緩存失效的問題,當前的解決辦法是安排在夜間進行擴縮容,并在擴縮容完成后重新運行當天的查詢。這樣,數據緩存會重新分布,并確保緩存的有效性。這一策略保證了在集群擴縮容后,DataCache功能能夠快速恢復。
在我們的實際場景中,針對線上的兩個典型查詢案例進行了分析,截取了查詢的執行Profile,結果顯示,DataCache的命中率相當高,幾乎達到理想狀態。這個效果的原因主要有以下幾點:
首先,由于數據集大多屬于T+1級別的數據,上午生成的數據在下午一般不會發生變化。這樣一來,用戶查詢的數據集基本保持一致,查詢模式趨于穩定。這種情況下,DataCache能夠高效緩存熱點數據,減少了重復的數據拉取,顯著提升了查詢性能。
其次,每天的查詢習慣大致相同,尤其是同一天內,用戶查詢的需求往往會集中在相似的時間段和數據范圍。因此,數據緩存策略能夠在用戶查詢峰值時,提供足夠的緩存支持,從而減少了帶寬消耗,并加速了查詢響應。
通過對比開啟和關閉DataCache時的監控數據,我們可以在Grafana中清晰地看到,開啟DataCache后,網卡流量顯著降低,節省的帶寬幾乎達到了2到3倍。
大查詢優化策略
在面對大查詢帶來的性能瓶頸時,我們實施了大查詢優化策略,以確保自助分析平臺能夠在數據量激增的情況下,繼續保持高效的查詢響應能力。
隨著某些業務的快速增長,新數據分區的數量急劇增加,導致某些查詢涉及的單個分區數據量大幅上升。例如,某些數據集的單分區數據量從年初的100億,已經增長至目前的200多億。這種數據量的增長可能會導致查詢過慢,甚至影響系統的整體性能,特別是在沒有有效優化的情況下。
為了應對這一挑戰,我們為StarRocks中的Iceberg表實現了 EXPLAIN ESTIMATE 功能。該功能能夠在實際查詢之前估算查詢的數據量。如果預估結果顯示查詢的數據量超過某個設定的閾值,系統會智能地將查詢請求引導到一個規模較小的StarRocks集群,或者是Spark集群來執行,從而避免超大查詢占用過多計算資源。這不僅減少了對其他查詢的影響,也降低了查詢超時的風險。
從性能監控數據來看,開啟此優化功能后,整體集群的CPU使用率得到了有效控制。特別是在大查詢出現時,CPU的負載沒有急劇攀升,避免了計算資源的過度消耗。相對而言,P90響應時間在開啟該優化后表現更為平穩,避免了因資源過載而導致的性能急劇下降。
項目收益
根據我們的測量結果,從年初到現在, P90 響應時間提升了三倍,當前的查詢響應時間大約可以控制在10秒以內 。
此外,通過優化存儲方式,尤其是應用Iceberg的Parquet存儲格式(如版本1.12),我們在存儲效率上也獲得了顯著的提升。與原有的ClickHouse存量分離版本相比,采用Iceberg存儲后,盡管數據量和行數保持一致, 但實際存儲空間減少了一半 。
未來規劃
未來規劃中,我們將探索結合 StarRocks 和 Paimon 的近實時湖倉分析架構,圍繞公司業務需求,進一步優化近實時鏈路的處理能力,并針對具有主鍵(PK)需求的湖上分析場景,制定更高效的優化方案。
直播回放:https://www.bilibili.com/video/BV18EC5YuEcA/?vd_source=1cb452610138142d1300dd37a6162a88
延伸閱讀:
StarRocks 助力小紅書離線數倉提效,提升百倍回刷性能!
StarRocks 在小紅書自助分析場景的應用與實踐
更多交流,聯系我們:StarRocks