從一個OLAP數據庫遷移到另一個數據庫是一項艱巨的工程。即使能找到一些有用的數據工具,您可能仍會猶豫是否對數據架構進行大手術,因為不確定如何運作。
本文分享如何從ClickHouse遷移到Doris的過程,包括為什么需要更改,需要注意什么以及如何比較兩個數據庫在各自環境中的性能。
1 使用Doris替換Kylin、ClickHouse和Druid
這里有一家電子商務SaaS提供商,其數據系統提供實時和離線報告、客戶分割和日志分析服務。最初,他們為這些不同的目的使用了不同的OLAP引擎:
- Apache Kylin用于離線報告:該系統為超過500萬個賣家提供離線報告服務。其中的大型賣家擁有超過1000萬注冊會員和100,000個SKU,詳細信息放在平臺上的400多個數據立方體中。
- ClickHouse用于客戶分割和Top-N日志查詢:這需要高頻更新、高QPS和復雜的SQL。
- Apache Druid用于實時報告:賣家通過組合不同的維度提取所需的數據,這種實時報告需要快速的數據更新、快速的查詢響應和系統的強大穩定性。
這三個組件都有各自的痛點:
- Apache Kylin在固定表模式下運行良好,但每次添加維度時,需要創建一個新的數據立方體并在其中重新填充歷史數據。
- ClickHouse不適用于多表處理,因此需要額外的解決方案來進行聯合查詢和多表連接查詢。在高并發場景下,它的表現低于預期。
- Apache Druid實現了冪等寫入,因此它本身不支持數據更新或刪除。這意味著當上游出現問題時,需要進行完整的數據替換。如果您從頭到尾考慮所有數據備份和移動,這樣的數據修復是一個多步驟的過程。此外,新攝入的數據在放入Druid中的段之前將無法用于查詢。這意味著存在更長的時間窗口,從而導致上下游之間的數據不一致。
由于它們共同工作,這種架構可能太難以導航,因為它需要在開發、監控和維護方面了解所有這些組件。此外,每次用戶擴展集群時,他們必須停止當前集群并遷移所有數據庫和表,這不僅是一個巨大的任務,而且會對業務造成巨大的干擾。
圖片
Apache Doris填補了這些空白。
- 查詢性能:Doris擅長高并發查詢和連接查詢,并且現在配備了倒排索引以加速日志搜索。
- 數據更新:Doris的唯一鍵模型支持大容量更新和高頻實時寫入,而重復鍵模型和唯一鍵模型支持部分列更新。它還提供數據寫入的恰好一次保證,并確保基表、物化視圖和副本之間的一致性。
- 維護:Doris與MySQL兼容。它支持輕松擴展和輕量級模式更改。它配備了自己的集成工具,如Flink-Doris-Connector和Spark-Doris-Connector。
因此,計劃進行遷移。
2 替換手術
ClickHouse是舊數據架構中的主要性能瓶頸,也是最初想要進行更改的原因,因此從ClickHouse開始。
2.1 SQL語句的更改
表創建語句
圖片
這里構建了自己的SQL重寫工具,可以將ClickHouse表創建語句轉換為Doris表創建語句。該工具可以自動執行以下更改:
- 映射字段類型:它將ClickHouse字段類型轉換為Doris中對應的字段類型。例如,它將String作為Key轉換為Varchar,將String作為分區字段轉換為Date V2。
- 在動態分區表中設置歷史分區的數量:某些表具有歷史分區,應在Doris表創建時指定分區數,否則將拋出“無分區”錯誤。
- 確定桶的數量:它根據歷史分區的數據量來決定桶的數量;對于非分區表,它根據歷史數據量來確定桶的配置。
- 確定TTL:它確定動態分區表中分區的生存時間。
- 設置導入順序:對于Doris的唯一鍵模型,它可以根據Sequence列指定數據導入順序,以確保數據攝入的有序性。
圖片
查詢語句
同樣,也有工具可以將ClickHouse查詢語句轉換為Doris查詢語句。這是為了準備ClickHouse和Doris之間的比較測試。轉換中的關鍵考慮因素包括:
- 表名的轉換:這很簡單,只需按照表創建語句中的映射規則進行即可。
- 函數的轉換:例如,ClickHouse中的
COUNTIF
函數等價于SUM(CASE WHEN_THEN 1 ELSE 0)
,Array Join
等價于Explode
和Lateral View
,而ORDER BY
和GROUP BY
應轉換為窗口函數。 - 語義上的差異:ClickHouse按照自己的協議進行操作,而Doris兼容MySQL,因此需要為子查詢設置別名。在這種情況下,子查詢在客戶分割中很常見,因此他們使用
sqlparse
。
2.2 數據攝入方法的變化
圖片
Apache Doris提供了廣泛的數據寫入方法。對于實時鏈接,采用Stream Load從NSQ和Kafka攝取數據。
對于大型離線數據,測試了不同的方法,以下是結論:
- Insert Into 使用Multi-Catalog讀取外部數據源并使用Insert Into進行攝取可以滿足此用例中的大多數需求。
- Stream Load
Spark-Doris-Connector是一種更通用的方法。它可以處理大量數據并確保寫入穩定性。關鍵是找到正確的寫入速度和并行性。
Spark-Doris-Connector還支持Bitmap。它允許您將Bitmap數據的計算工作負載移動到Spark集群中。
Spark-Doris-Connector和Flink-Doris-Connector都依賴于Stream Load。CSV是推薦的格式選擇。用戶的數十億行測試表明,CSV比JSON快40%。
- Spark Load
Spark Load方法利用Spark資源進行數據洗牌和排名。計算結果放在HDFS中,然后Doris直接從HDFS讀取文件(通過Broker Load)。這種方法非常適合大規模數據攝入。數據越多,攝入速度越快,資源利用率越高。
3 壓力測試
這里比較了兩個組件在SQL和連接查詢方案上的性能,并計算了Apache Doris的CPU和內存消耗。
3.1 SQL查詢性能
Apache Doris在16個SQL查詢中的10個中表現優于ClickHouse,最大的性能差距比例接近30。總體而言,Apache Doris比ClickHouse快2~3倍。
圖片
3.2 連接查詢性能
對于連接查詢測試,使用了不同大小的主表和維表。
- 主表:用戶活動表(40億行)、用戶屬性表(250億行)和用戶屬性表(960億行)
- 維表:100萬行、1000萬行、5000萬行、1億行、5億行、10億行和25億行。
測試包括完全連接查詢和過濾連接查詢。完全連接查詢連接主表和維表的所有行,而過濾連接查詢使用WHERE
過濾器檢索特定賣家ID的數據。結果如下:
主表(40億行):
- 完全連接查詢:Doris在所有維表的完全連接查詢中均優于ClickHouse。隨著維表變大,性能差距越來越大。最大的差距比例接近5。
- 過濾連接查詢:基于賣家ID,過濾器從主表中篩選出了4100萬行。對于小型維表,Doris比ClickHouse快2~3倍;對于大型維表,Doris比ClickHouse快10倍以上;對于大于1億行的維表,ClickHouse會拋出OOM錯誤,而Doris則正常運行。
主表(250億行):
- 完全連接查詢:Doris在所有維表的完全連接查詢中均優于ClickHouse。ClickHouse在維表大于5000萬行時會產生OOM錯誤。
- 過濾連接查詢:過濾器從主表中篩選出了5.7億行。Doris在幾秒鐘內響應,而ClickHouse在連接大型維表時完成時間為幾分鐘,并在此過程中崩潰。
主表(960億行):
Doris在所有查詢中都表現出相對較快的性能,而ClickHouse無法執行所有查詢。
在CPU和內存消耗方面,Apache Doris在所有大小的連接查詢中都保持穩定的集群負載。