Cloudflare 診斷 ClickHouse 查詢規劃器 Mutex 競爭:從 flame graph 到上游 PR
Cloudflare Blog · 2026-05-14
Cloudflare 工程師記錄了一次 ClickHouse 效能調查:計費流水線在分區方案從 (namespace, day) 遷移後查詢開始大幅降速,即使 CPU 指標看起來正常。根本原因是查詢規劃器(query planner)對分區清單持有一把排他鎖(exclusive mutex),在 160,000+ 個分區與數百個並發查詢的規模下,超過一半的查詢時間都花在等待這把鎖上。三項優化最終合入 ClickHouse 25.11 版(上游 PR #85535)。
原本的問題
查詢規劃器的執行邏輯是:鎖定整個分區清單(排他鎖)→ 複製所有分區到記憶體 → 篩選出相關分區。隨著分區數從 30,000 增長到 160,000+,每個並發查詢都必須等待其他查詢完成複製操作後才能取得鎖,形成嚴重的串行化瓶頸。
診斷方式
初期使用 CPU flame graph 未發現異常,因為問題是等待(waiting)而非計算(computing)。關鍵突破是切換到 ClickHouse 內建 trace_log 的「Real」模式,這個模式會捕捉被阻塞的執行緒,從而讓 mutex 等待在 flame graph 中清晰可見。
三項優化
- Shared Lock:將排他鎖改為
std::shared_lock,允許多個讀取者並發存取 - 消除向量複製:建立分區清單的快取共享副本,規劃器只複製篩選後的結果,而非先複製全部再篩選
- Binary Search:利用分區 ID 的有序性實作 binary search,對依 namespace 篩選的場景特別有效
影響範圍
修復後查詢時間顯著下降,且在分區數持續增長到 160k 後依然穩定。最重要的經驗是診斷工具的選擇:CPU 層面的 profiling 對於 I/O 或 lock 導致的延遲問題是盲目的,需要使用能捕捉「執行緒在等什麼」的 wall-clock/real-time profiling 工具。
原始來源:Cloudflare Blog
ClickHouse 26.4:NATURAL JOIN、JSON 子欄位索引與 COUNT DISTINCT 3–15× 提速
ClickHouse Blog · 2026-05-08
ClickHouse 26.4 釋出,共包含 39 個新功能、45 項效能優化與 238 個 bug 修復。主要亮點包括 SQL 標準相容性擴充(NATURAL JOIN、OVERLAY、EXTRACT EPOCH 等)、JSON 子欄位文字索引,以及 COUNT DISTINCT 在高核心機器上的顯著提速。
SQL 相容性擴充
- NATURAL JOIN:根據同名欄位自動 JOIN,減少 USING 子句撰寫
- VALUES 作為 Table Expression:現可在
FROM子句中使用 VALUES 並指定欄位別名 - EXTRACT EPOCH/DOW/ISOYEAR/CENTURY:支援 PostgreSQL 風格的時間單位
- SET TIME ZONE:符合 SQL 標準的時區設定語法
- 複合 INTERVAL 字面量:例如
INTERVAL '1 year 3 months'
效能改進
COUNT DISTINCT 在高核心機器上的提速幅度為 3–15×。原本實作在 merge 操作時對 256 個 hash table buckets 各自啟動執行緒,造成大量不必要的執行緒生成。新實作將 N 個中間 hash table 在單一 pass 中合併,執行緒池初始化複雜度從 O(N) 降為 O(1)。
LIKE 查詢透過文字索引字典掃描優化,查詢速度提升超過 3×,掃描資料量減少 80%。JSON 欄位方面,在 JSONAllValues(返回所有葉子節點值的陣列)上建立文字索引後,掃描範圍縮小約 5×,查詢時間減少約 50%。
影響範圍
NATURAL JOIN 與 EXTRACT EPOCH 的支援讓從 PostgreSQL 遷移 SQL 查詢更加平滑。對於大量使用 COUNT DISTINCT 的分析工作負載,26.4 在多核心伺服器上的提升尤其顯著,無需修改 SQL 即可受益。
原始來源:ClickHouse Blog
DuckDB Quack:基於 HTTP/TCP 的 Client-Server 協定,跨進程並行寫入終於實現
DuckDB Blog · 2026-05-12
DuckDB 團隊發布 Quack 協定,讓多個獨立進程(本地或遠端)可以並行修改同一個 DuckDB 資料庫的表格,而不受原本 in-process 架構的互斥限制。協定預設監聽 port 9494(紀念 Netscape Navigator 1994 年),連線命令為 ATTACH 'quack:localhost'。
規格細節
Quack 選擇 HTTP/TCP 而非自定義二進位協定,理由是現有的負載平衡、防火牆、身份驗證基礎設施都已針對 HTTP 最佳化,無需重複發明。序列化使用自訂 MIME type application/duckdb,底層序列化原語與 Write-Ahead Log 相同,是已充分測試的成熟機制。
安全模型方面:伺服器啟動時自動生成隨機身份驗證 token,預設只綁定 localhost。對外暴露時建議透過 nginx 反向代理搭配 SSL/Let's Encrypt。
效能數據
| 場景 | Quack | Arrow Flight SQL | PostgreSQL |
|---|---|---|---|
| 60M rows 大量傳輸 | 4.94s | 17.40s | 158.37s |
| 8 執行緒並行小寫入 | ~5,434 TPS | ~1,358 TPS | ~4,320 TPS |
影響範圍
Quack 是 DuckDB 從「嵌入式分析引擎」走向「可部署資料服務」的關鍵一步。目前在超過 8 個並行執行緒時吞吐量會達到瓶頸,這是 DuckDB 並行插入架構本身的限制,團隊已列入未來優化方向。對於需要多個服務共享一個 DuckDB 資料庫的架構,Quack 是目前唯一的官方方案。
原始來源:DuckDB Blog