ClickHouse十大最佳實踐技巧
本文字數16642估計閱讀時間42 分鐘作者Yonatan DolanClickHouse 是一款開源的列式數據庫管理系統(tǒng)專為對海量數據集進行實時分析查詢而設計。它擅長在數毫秒內聚合數十億行數據使其成為分析平臺、可觀測性系統(tǒng)、實時儀表盤和數據倉庫的流行選擇。ClickHouse 通過其列式存儲格式、高效壓縮和向量化查詢執(zhí)行來實現(xiàn)這一目標但要獲得最佳性能需要理解如何與其架構協(xié)同工作。盡管 ClickHouse 具備卓越的開箱即用性能但設計不佳的 Schema、低效的查詢或次優(yōu)的配置都可能浪費大量的性能潛力。一個原本能在數毫秒內返回結果的表可能需要數秒。能實現(xiàn) 50 倍壓縮的存儲可能最終只能達到 10 倍。這種性能差距往往源于未能理解 ClickHouse 如何存儲、壓縮和查詢數據并應用正確的技術來使您的用例與其優(yōu)勢相匹配。無論您是每天插入數十億事件、運行復雜的分析查詢還是努力降低存儲成本正確的優(yōu)化都能顯著提升性能和效率。對數據類型、表引擎或排序鍵的微小調整都可能帶來數量級的改進。在本文中我將分享 10 項最佳實踐這些是我作為 ClickHouse 解決方案架構師在日常與客戶緊密合作中發(fā)現(xiàn)能夠帶來最大影響的。它們并非紙上談兵的理論建議而是我在各種規(guī)模的部署中反復運用并取得成效的模式涵蓋了從 Schema 設計、數據建模到查詢優(yōu)化和監(jiān)控等多個主題。將 ClickHouse 與 AI 代理一同使用如果您正通過 AI 代理或大型語言模型 (LLM) 應用程序查詢 ClickHouse請查閱 ClickHouse best practices for AI agents獲取針對該用例的專屬指南(https://clickhouse.com/blog/introducing-clickhouse-agent-skills)。1. 選擇合適的主鍵和排序鍵在 ClickHouse 中表定義中的ORDER BY子句是您做出的最關鍵決策之一。它決定了數據在存儲中的物理排序方式這直接影響查詢通過主索引剪枝 (primary index pruning) 跳過無關數據的效率。同時它還會影響壓縮效率因為排序后的數據中相鄰行通常共享相似值從而能實現(xiàn)更高的壓縮比。ClickHouse 寫入數據時會根據您指定的ORDER BY列對行進行排序并在內存中存儲每個數據顆粒granule默認為 8,192 行的首個值。在查詢時對這些列應用的過濾器可讓 ClickHouse 跳過那些無法包含匹配數據的整個數據顆粒。關鍵在于使您的ORDER BY順序與最常見的查詢模式保持一致。優(yōu)先放置像tenant_id、region或category這樣的低基數low-cardinality列隨后是基于時間的列。應避免以 UUIDs 或 timestamp 等高基數high-cardinality字段開頭因為它們幾乎無法提供裁剪優(yōu)化效果。讓我們以包含逾 1.5 億行數據的 Amazon reviews dataset 為例。假設一個表默認按(marketplace, customer_id, review_date)排序執(zhí)行以下查詢SELECT product_category, toStartOfMonth(review_date) AS month, count() AS review_count, avg(star_rating) AS avg_rating FROM amazon_reviews WHERE product_category Electronics AND toYear(review_date) 1999 GROUP BY product_category, month ORDER BY month;它會執(zhí)行一次全表掃描遍歷全部 1.5 億行數據以查找極小部分數據。如果我們更改表的ORDER BY順序為(product_category, review_date)我們的查詢將基于這些列進行過濾從而使相同的查詢運行速度提升 3 倍同時所需掃描的數據量減少 347 倍。對于相同的查詢和數據集如果ORDER BY順序與查詢模式匹配便能帶來顯著的不同。2. 使用高效數據類型ClickHouse 中的數據類型不僅僅關乎正確性它們直接影響存儲大小、壓縮比和查詢速度。選擇適合數據的最小類型除非NULL值確實具有實際意義否則避免使用Nullable(可為空) 類型對于低基數文本列使用LowCardinality(String)(低基數字符串) 類型以及對于固定值集合優(yōu)先選擇Enum(枚舉) 類型而非自由文本字符串可以顯著提升性能和存儲效率。同樣的邏輯也適用于整數類型當數據范圍允許時使用UInt8或UInt32代替UInt64意味著每次查詢需要讀取、解壓縮和處理的數據量更少。 被標記為Nullable(可為空) 的列要求 ClickHouse 額外存儲一個UInt8列來追蹤NULL值這會增加存儲和查詢執(zhí)行的雙重開銷。因此除非NULL值確實具有實際意義否則最好避免使用Nullable類型。在大多數情況下一個合理的默認值可以作為有效的替代方案文本字段使用空字符串、數值計數使用0、或者對于0是有效條目的 ID 字段使用像-1這樣的哨兵值。對于值集有限的字符串列LowCardinality(String)(低基數字符串) 類型在底層使用字典編碼這使得它在列中不同值少于約 10,000 個時效率更高。讓我們繼續(xù)以擁有 1.5 億行數據的 Amazon 評論數據集為例。一個設計不佳的表其中許多列是Nullable(可為空) 類型、數值字段過大、低基數文本列使用普通String類型會占用30.16 GB存儲空間。通過優(yōu)化即通過刪除Nullable(可為空) 類型、調整數值列大小、并在適當位置應用LowCardinality(String)(低基數字符串) 類型將其切換到更合適的數據類型后存儲空間可降至26.8 GB。但其價值不僅僅體現(xiàn)在存儲方面它對性能也有顯著提升如下例所示查詢速度提高了2 倍。3. 考慮分區(qū)策略或避免使用分區(qū)ClickHouse 中的分區(qū) (partitioning) 是最容易被誤解的特性之一最常見的錯誤是將其用作性能優(yōu)化手段。ClickHouse 中的分區(qū)主要是一種數據管理特性而非通用的性能加速器。ClickHouse 通過主索引剪枝 (primary index pruning) 在數據跳過方面已經極其快速。在此基礎上再進行分區(qū)很少有幫助反而常常適得其反。原因是 ClickHouse 需要大的數據塊 (parts)通常高達 150GB常含數十億行數據才能高效地進行壓縮和查詢并且數據塊 (parts) 永遠不會跨分區(qū)邊界合并。過度分區(qū)例如按天或按高基數 (high-cardinality) 列如 tenant_id進行常常導致大量小數據塊 (parts)、合并速度變慢、內存占用增加以及查詢性能下降。一個好的經驗法則如果您創(chuàng)建了超過幾十個分區(qū)您很可能正在過度分區(qū)。那么何時應該進行分區(qū)呢在兩種情況下對數據進行分區(qū)是很有價值的。第一種情況是基于 Time-to-Live (TTL) 的數據過期按月或按年分區(qū)可以高效地刪除整個舊數據分區(qū)而無需觸發(fā)變異 (mutation) 或合并 (merge) 操作這對于大型數據集來說比行級 TTL 效率高得多。第二種情況是與 ReplacingMergeTree、CollapsingMergeTree 或 AggregatingMergeTree 等合并型表引擎 (merge-oriented table engines) 配合使用時通過為歷史分區(qū)保留一個數據塊 (part)我們可以在帶有 FINAL 修飾符的查詢中獲得顯著的性能提升。除了這兩種情況在添加 PARTITION BY (分區(qū)子句) 之前請務必謹慎考慮。默認的不分區(qū)或者簡單的按月或按年分區(qū)通常是正確的選擇。為了說明不必要分區(qū)的成本我們在兩個結構相同的表上使用了包含 1.5 億行 Amazon 評論的同一份數據集進行測試。其中一個表按review_date的月份進行分區(qū)另一個則未分區(qū)。數據攝入時間大致相同294 秒 對 314 秒但分區(qū)表在加載過程中消耗了多達 55% 的內存4.71 GB 對 3.03 GB。真正的性能損耗體現(xiàn)在查詢階段。一個針對所有product_category值進行簡單聚合的查詢在未分區(qū)表上僅需 0.4 秒而在分區(qū)表上則耗時 20 秒。盡管掃描了完全相同的行數但性能下降了 46 倍。一個按helpful_votes進行 Top-100 排序的查詢也展現(xiàn)了類似但程度稍輕的性能差異未分區(qū)表耗時 40 秒分區(qū)表則耗時 92 秒。同樣的數據同樣的查詢速度卻慢了一倍以上。由于這兩個查詢均未對review_date進行過濾分區(qū)并未帶來任何剪枝 (pruning) 優(yōu)化。相反數據碎片化反而增加了每次掃描時的合并與調度開銷。4. 使用跳過索引 (Skipping Indexes) 優(yōu)化數據掃描ClickHouse 的主索引是基于ORDER BY字段構建的稀疏索引是實現(xiàn)快速數據訪問最強大的工具。但在實際應用中查詢并非總能通過主鍵列進行過濾。在這種情況下跳過索引 (Skipping Indexes) 能夠將相同的數據粒度剪枝 (granule-pruning) 能力擴展到數據模型中的任意其他列。跳過索引是與數據一同存儲的輔助索引它不會改變數據的物理存儲和排序方式。跳過索引有多種類型我們可以將它們大致分為兩類輕量級索引 (Lightweight Indexes) 和重量級索引 (Heavyweight Indexes)。輕量級索引對寫入性能和存儲的影響微乎其微因此可以在任何有助于提升查詢效率的地方自由添加。而重量級索引則會帶來更高的存儲開銷和寫入放大 (write amplification) 成本。因此只有當查詢加速效果顯著且足以抵消這些額外開銷時才值得考慮使用。輕量級索引 (Lightweight Indexes)? minmax - 針對每個數據粒度 (granule) 存儲其最小值和最大值。最適用于數值或日期列對字符串列也可能有所幫助。其構建與維護成本極低存儲開銷幾乎可以忽略不計。? set - 針對每個數據粒度存儲一小組獨特的distinct值。最適合經常用于過濾條件但未包含在 ORDER BY 子句中的低基數 (low-cardinality) 列??梢酝ㄟ^ set(0) 來存儲所有唯一值或者使用 set(N) 來設定上限當超出此上限時查詢將回退到全表掃描。重量級索引 (Heavyweight Indexes)bloom_filter- 一種概率型數據結構用于判斷“某個值是否確定不在當前數據塊中”。最適用于高基數字符串列例如 ID 或 URL。它允許存在誤報但絕無漏報。由于會帶來顯著的存儲和寫入開銷因此僅當其帶來的掃描優(yōu)化能夠抵消其成本時才應使用。ngrambf_v1/tokenbf_v1- 是bloom_filter的變體專門針對自由文本列上的LIKE或hasToken查詢進行了優(yōu)化。雖然在子字符串和詞元token搜索方面表現(xiàn)強大但其構建和存儲成本較高因此僅應在經常進行搜索的列上使用。Text- 一種全新的自 26.2 版本起正式發(fā)布即 GA文本搜索專用倒排索引其功能類似于 Lucene/Elasticsearch 等系統(tǒng)中的倒排索引。它支持高精度的精確詞條term、前綴和子字符串匹配。它是文本搜索場景中最強大的選擇但同時在存儲和寫入放大方面也是開銷最大的。當Bloom_filter無法滿足您的性能需求時可選用Text索引。通過 Amazon 評論數據集可以很好地說明跳過索引skipping index的優(yōu)勢。當執(zhí)行一個total_votes 1000的過濾查詢時如果沒有跳過索引系統(tǒng)將對全部 1.5 億行數據執(zhí)行全表掃描。若在total_votes列上添加一個minmax索引這是開銷最低的索引之一掃描的行數將降至 2900 萬行實現(xiàn)高達80% 的數據掃描量減少且?guī)缀醪粠眍~外開銷。5. Leveraging the JSON Data Type for semi-structured dataClickHouse 的原生JSON數據類型是處理半結構化數據的強大工具特別適用于那些鍵值不可預測、隨時間變化或包含多種類型值的場景。它能夠在插入數據時自動推斷類型并將每個被發(fā)現(xiàn)的路徑存儲為獨立的子列受限于max_dynamic_paths的定義從而為動態(tài)數據提供列式存儲的性能優(yōu)勢。然而這種靈活性并非沒有代價。JSON類型在每次數據插入時都會執(zhí)行類型推斷這相比靜態(tài) Schema 會帶來額外的開銷。此外當同一路徑下包含多種類型的值時它還會占用更多的存儲空間。對于結構已知且一致的數據即使數據以 JSON 格式傳輸采用帶有顯式列類型的靜態(tài) Schema 也將始終比JSON類型表現(xiàn)出更優(yōu)的性能。在使用 JSON (JavaScript Object Notation) 數據時一個關鍵參數是max_dynamic_paths它控制 ClickHouse 將多少個不同的 JSON 路徑作為單獨的子列進行存儲。默認情況下一旦超出此限制其他路徑將被存儲在一個共享結構中這會降低查詢效率。默認值為 1024但對于路徑集有限且結構明確的有效載荷將其設置得更低可以使數據結構更緊湊、更可預測。當您知道某些路徑始終存在且類型固定時可以使用 JSON 提示 (hints) 明確聲明這些路徑。例如CREATE TABLE events ( id UInt64, payload JSON(timestamp DateTime, level LowCardinality(String)) ) ENGINE MergeTree ORDER BY id;提示 (Hints) 為 ClickHouse 提供了有關這些路徑的更多信息這些路徑像常規(guī)列一樣被存儲和壓縮而有效載荷的其余部分則保持完全動態(tài)。在將 Amazon Reviews 數據集轉換為文檔型數據集時相比不使用提示的 JSON使用提示可將存儲空間減少 38%同時此示例查詢的速度在使用提示時比不使用提示時提高了 26%。SELECT count(*), review_data.product_category PC FROM amazon_reviews_json GROUP BY pc然而這不僅是為了優(yōu)化存儲和提升性能提示路徑也是跳過索引 (skipping indexes) 的可靠目標而完全動態(tài)的路徑在不同數據粒度 (granules) 之間可能存在不一致從而導致索引效率較低。需要指出的是雖然可以在任何 JSON 路徑上添加跳過索引但這需要進行類型轉換 (casting)。總而言之如果數據結構扁平且可預測應使用顯式列 (explicit columns)。如果數據存在可預測的核心結構但伴隨動態(tài)變化則考慮對已知部分使用靜態(tài)列 (static columns)其余部分使用單個JSON列。只有當數據模式完全不可預測時才應考慮使用完全動態(tài)的JSON列。6. 正確地將數據導入 ClickHouse如何高效地將數據插入 ClickHouse 是一個值得深入探討的重要議題。數據攝取 (ingestion) 模式通常有四種每種模式都有其推薦的方法和最佳實踐。對象存儲(Object Storage)如 Amazon S3、GCS、Azure Blob是批量加載最常見的數據源之一。在有格式選擇時建議優(yōu)先選擇 Parquet 或 ORC 等列式格式而不是 JSON 或 Avro 等行式格式ClickHouse 可以僅從 Parquet 和 ORC 格式中讀取所需列完全跳過其余部分而 JSON 則需要解析每一行的每個字段。即使在加載所有列時列式格式也更快因為數據到達時已按照 ClickHouse 內部存儲的方式組織從而減少了攝取過程中的轉換開銷。加載 Amazon reviews 數據集清楚地說明了這一點Parquet 和 ORC 格式加載耗時79 秒Avro 格式耗時94 秒JSON 格式耗時105 秒。對于從對象存儲進行托管式持續(xù)數據攝取ClickPipes 直接支持 S3 和 GCS 數據源。數據庫的CDC(Change Data Capture)如 Postgres、MySQL、MongoDB 等和事件流如 Kafka、Kinesis 等最好通過 ClickHouse Cloud 的原生托管式攝取服務 ClickPipes 來處理。ClickPipes 開箱即用地支持模式映射、偏移量管理、錯誤處理和背壓。針對 CDC它采用基于日志的方法以最小的源數據庫負載捕獲每一行級別的變更。如果您的數據庫位于私有 VPC (Virtual Private Cloud) 中ClickPipes 支持反向 PrivateLink從而實現(xiàn)安全連接而無需將數據庫暴露給公共互聯(lián)網。后端應用程序直接寫入 ClickHouse 是企業(yè)非常普遍的做法但這確實需要考慮一些事項。ClickHouse 針對大型、不頻繁的批次進行了優(yōu)化而非應用程序代碼中常見的小型、頻繁的插入。每次插入都會在存儲層中創(chuàng)建至少一個部分 (part)而過多的小部分會導致合并壓力 (merge pressure)、內存使用量升高并最終導致插入限流 (insert throttling)。兩種解決方案是客戶端批量處理累積行并在每隔幾秒或幾千行時刷新或者啟用異步插入(async inserts)這讓 ClickHouse 自動緩沖傳入的插入并以批次形式刷新它們SET async_insert 1; SET wait_for_async_insert 1;當wait_for_async_insert 1時客戶端會等待數據寫入分片part的確認這為您提供了小批量寫入的便利并具備適當的確認機制和可靠的錯誤處理能力。您可以通過system.asynchronous_insert_log監(jiān)控異步插入行為從而針對您的工作負載調整刷新間隔和緩沖區(qū)大小。無論采用何種數據導入方式請避免一次只插入一行數據在可能的情況下優(yōu)先選擇原生二進制格式而非 JSON并通過監(jiān)控system.parts中的分片part數量盡早發(fā)現(xiàn)數據導入問題。7. 寫入時計算借助物化視圖Materialized View和投影Projection實現(xiàn)更快的讀取物化視圖和投影都遵循相同的核心思想在數據插入時執(zhí)行計算從而使讀取操作更快并減少計算資源消耗。與在查詢時進行掃描和聚合不同您可以選擇在數據到達時預先計算并存儲結果。兩者的權衡取舍是一致的更快的讀取是以增加存儲空間和額外的寫入開銷為代價的。投影是存儲在同一表內部的替代排序方式或預聚合數據。當 ClickHouse 執(zhí)行查詢時如果查詢的過濾和排序模式與某個投影匹配它會自動選擇最佳投影因此無需對查詢進行任何修改。這使得它們對應用程序透明易于采用。缺點在于每次插入操作都必須為每個投影寫入和排序數據這會增加插入延遲和存儲占用。在圍繞投影制定查詢優(yōu)化策略之前有必要驗證它們是否真正在查詢時被選中。最簡單的方法是啟用以下設置SET force_optimize_projection 1;啟用此設置后如果您的查詢沒有找到合適的投影ClickHouse 將拋出錯誤從而立即明確您的投影是正在被使用抑或是被默默忽略。關于投影需要強調的一點是它們常常被“以防萬一”地添加這會影響存儲和寫入成本。首先應該使用設計良好的主鍵并識別出實際運行緩慢的查詢然后只在真正需要的地方添加投影。讓實際使用數據來指導投影的定義。物化視圖 (Materialized views)有兩種類型??伤⑿挛锘晥D (Refreshable materialized views)的工作方式與傳統(tǒng)數據倉庫中的預期一致它們會按計劃重新計算結果因此適用于復雜的轉換。但這種方式通常需要管理已處理數據的“書簽”以區(qū)分已處理和未處理的數據在遇到延遲數據或歷史數據回填時需要進行重新處理同時強烈建議在處理過程中考慮冪等性。增量物化視圖 (Incremental materialized views)是 ClickHouse 的獨特之處它們更靈活但也需要更精心設計。它們充當插入觸發(fā)器對每個傳入批次運行SELECT查詢并將結果寫入目標表。這使得它們在數據到達時能夠極其高效地持續(xù)維護聚合、匯總或扇出數據管道。一個重要的限制是它們僅在插入操作時觸發(fā)對源表的刪除和更新操作不會傳播因此它們最適合僅追加或不可變的數據模式。增量物化視圖中的連接操作值得特別關注因為只有連接中的左表會觸發(fā)視圖更新。如果右側表發(fā)生變化物化視圖將不會更新。此外物化視圖的良好可組合性也值得了解單個源表可以“扇出”到多個物化視圖MV每個 MV 維護不同的聚合或轉換同時來自不同源表的多個 MV 也可以匯聚到同一個目標表。這使得它們成為構建更復雜數據管道的強大基石。在 ClickHouse 中一種常見模式是利用物化視圖來維護用于儀表盤和高頻查詢的預聚合匯總表同時保留原始表以進行即席探索。8. 了解你的系統(tǒng)表ClickHouse 的系統(tǒng)表是其最強大的內置功能之一。集群中發(fā)生的一切包括查詢、合并、后臺活動和錯誤都被捕獲并可以通過標準 SQL 進行查詢從而使用標準 SQL 為你提供深入的可觀測性。在多副本服務中查詢系統(tǒng)表僅會顯示當前查詢所在副本的日志。若要獲取所有副本的完整視圖需使用clusterAllReplicas。此外由于許多系統(tǒng)表會輪轉歷史數據可能不會直接顯示除非你顯式地通過merge表函數對它們進行合并。以下是如何查詢system.query_log以確保獲取表中所有服務日志的示例SELECT event_time, query_id, query, type FROM clusterAllReplicas(default, merge(system, ^query_log*)) WHERE event_time Now() - toIntervalMinute(5);system.query_log和system.parts是兩個最值得熟悉的系統(tǒng)表。system.query_log是理解查詢行為的主要工具。每個查詢會根據事件QueryStart、QueryFinish、ExceptionBeforeStart或ExceptionWhileProcessing生成一行記錄從而提供服務上所有查詢的完整生命周期視圖。每行數據會捕獲查詢耗時 (query_duration_ms)、資源使用情況 (read_rows、read_bytes、memory_usage)、查詢文本本身以及所涉及的數據庫、表、列和投影。在錯誤排查時還可以利用exception_code、exception和stack_trace。ProfileEvents列則提供了更深入的洞察它是一個低級執(zhí)行計數器的映射能夠精確揭示時間開銷分布從 CPU 周期到 I/O 讀取再到緩存命中。當查詢速度低于預期時ProfileEvents常常能幫助我們判斷瓶頸是在 I/O、CPU 還是網絡。system.parts表詳細展示了您的存儲中所有 MergeTree 系列表MergeTree-family tables的每個物理數據部分的信息。每行對應一個數據部分使其成為監(jiān)控存儲、診斷合并行為和理解表健康狀況的理想選擇。其中最關鍵的列包括active指示一個數據部分是當前活躍的還是已完成合并后留下的舊部分因此通過active 1進行過濾可確保查詢只關注活躍的相關部分。partition和partition_id顯示了每個數據部分所屬的分區(qū)而rows、bytes_on_disk、data_compressed_bytes和data_uncompressed_bytes則清晰地展示了數據部分的大小和壓縮效率。part_type區(qū)分Wide和Compact兩種數據部分它們決定了列的存儲方式。在Wide格式中每個列都存儲在各自獨立的文件中這是較大數據部分的標準格式并在讀取時實現(xiàn)了高效的列裁剪column pruning。Compact格式將所有列存儲在單個文件中默認小于 10MB這減少了文件句柄file handle的數量對于行數較少的小型數據部分而言效率更高。值得我們隨時取用的兩個查詢是各表的數據部分數量和大小SELECT table, count() AS parts, sum(rows) AS total_rows, formatReadableSize(sum(bytes_on_disk)) AS size_on_disk FROM system.parts WHERE active GROUP BY table ORDER BY parts DESC;過度分區(qū)表SELECT table, partition, count() AS parts FROM system.parts WHERE active GROUP BY table, partition HAVING parts 10 ORDER BY parts DESC;9. 精通 ReplacingMergeTreeReplacingMergeTree是 ClickHouse 中備受歡迎的表引擎之一它用于支持需要去重deduplication或更新插入upserts的場景。此表引擎根據指定列例如版本/時間戳保留每行的最新版本。去重操作依據ORDER BY列的唯一性進行。舊的重復數據會在后臺合并background merges過程中被舍棄。需要注意的是這些合并是異步進行的這意味著在查詢時表中可能仍然存在重復行。若要獲取正確的結果需要使用FINAL或argMax模式并深入理解它們之間的權衡。FINAL是最簡單的方式只需將其添加到查詢中ClickHouse 就會透明地處理去重操作。然而代價是FINAL在返回結果之前必須協(xié)調reconcile所有的數據部分其性能與查詢時存在的數據部分數量直接相關。在一個合并良好、分區(qū)中只有一個數據部分的表上使用FINAL與否性能差異不大。而在一個處于數據攝取ingestion中期、存在大量數據部分的表上它可能帶來顯著的性能開銷。SELECT star_rating FROM mytests.amazon_reviews_rmt FINAL WHERE review_id review_idargMax模式是一種替代方案它將去重邏輯整合到聚合操作本身中從具有最高版本的行中選取值SELECT argMax(star_rating, review_date) FROM mytests.amazon_reviews_rmt WHERE review_id review_id在包含 1.52 億行1.5 億原始行 200 萬重復行的 Amazon reviews 數據集上這兩種方法的性能差異與表的狀態(tài)密切相關。在存在 9 個未合并的數據分塊時上述使用FINAL的查詢耗時 1.5 秒而argMax耗時 1.0 秒。為了展示數據分塊更少時的差異我們強制將這些數據分塊合并為一個單一分塊此時兩種方法的性能均下降到大致相同的水平0.48 秒對比 0.40 秒。盡管具體結果可能因查詢形態(tài)、基數和數據分塊數量而異但這一規(guī)律依然成立無論合并狀態(tài)如何argMax都表現(xiàn)出更高的穩(wěn)定性而FINAL則隨著數據分塊的合并性能顯著提升。實際上對于日常查詢或當表數據合并良好時FINAL是一個更簡單的選擇。而當處理有活躍寫入的表并且需要可預測的延遲時argMax則更值得選用。在生產環(huán)境中減少FINAL性能不穩(wěn)定性的一種方法是配置后臺合并使其對舊數據處理得更積極。默認情況下ClickHouse 會根據內部啟發(fā)式算法合并數據分塊該算法會考慮數據分塊的大小、數量和創(chuàng)建時間但并沒有強制將一個分區(qū)的數據合并成一個單一分塊的機制。這意味著一個表可以無限期地保持每個分區(qū)擁有多個數據分塊從而導致FINAL持續(xù)產生額外開銷。min_age_to_force_merge_seconds設置改變了這一默認行為它會強制 ClickHouse 不斷合并早于指定閾值的數據分塊直到每個分區(qū)只剩下一個數據分塊min_age_to_force_merge_seconds 600, min_age_to_force_merge_on_partition_only 1;請注意這樣做可能會增加后臺合并的負載因為 ClickHouse 會持續(xù)合并數據分塊直到每個分區(qū)只剩下一個從而占用更多本可用于查詢或寫入的 CPU 和 I/O 資源。min_age_to_force_merge_on_partition_only 1標志確保此操作僅在所有數據塊parts都已足夠舊的分區(qū)上觸發(fā)從而避免干擾仍在活躍寫入的分區(qū)。值得注意的是為了使此設置在實踐中有效表應該進行分區(qū)。如果沒有分區(qū)所有數據將存儲在單個分區(qū)中可能積累過多的數據。由于 ClickHouse 默認不會合并會使數據塊大小超過 150GB 的分塊因此將所有數據整合為單個數據塊變得不切實際。通過按月或按年分區(qū)每個分區(qū)都將保持在可控的尺寸范圍內從而能夠合并為單個數據塊這正是FINAL操作性能最佳的狀態(tài)。10. 優(yōu)化你的 JOIN過去ClickHouse 中的 JOIN 曾是建議用戶謹慎使用的一個特性普遍的建議是盡可能通過反范式化denormalization、字典dictionaries或物化視圖materialized views來避免使用 JOIN。這一建議在當時是合理的但顯著的引擎級改進使 JOIN 在高并發(fā)生產工作負載中變得越來越可行。作為默認查詢執(zhí)行層引入的 Analyzer查詢優(yōu)化器為 JOIN 規(guī)劃帶來了重大改進ClickHouse 24.4 引入了更好的謂詞下推predicate pushdown功能通過將過濾條件推送到 JOIN 的兩側可將查詢性能提升 10 倍版本 24.12 獲得了自動重新排序雙表 JOIN 的能力將較小的表放在右側25.9 則將此功能擴展到連接三個或更多表的查詢。結合多種 JOIN 算法可供選擇以平衡不同的內存和性能考量如今 ClickHouse 中的 JOIN 其能力顯著增強也更容易正確使用甚至比一年前有了巨大的提升。盡管如此JOIN 在分析型數據庫中仍然伴隨著開銷因此有幾項原則值得遵循。對于對毫秒級延遲有嚴格要求的實時工作負載目標是每個查詢最多包含 3 到 4 個 JOIN。此外反范式化、字典或預聚合物化視圖是值得考慮用于進一步提升查詢性能的工具。對于靜態(tài)或變化緩慢的查找推薦使用字典。當需要用不常變動的小型參考表數據來豐富大型表時字典的性能將優(yōu)于常規(guī)連接。字典會完全加載到內存中并通過dictGet進行訪問從而徹底繞過哈希連接過程。以客戶元數據豐富后的 Amazon reviews 數據集為例性能差異顯著在 1.5 億行數據上執(zhí)行常規(guī)JOIN操作耗時2.3 秒與字典表進行連接耗時1.36 秒而dictGet操作僅需0.86 秒這比基準連接快了近 3 倍且底層數據無需修改??偨YClickHouse 開箱即用即表現(xiàn)出極快的速度但要充分發(fā)揮其潛力就必須深入理解其數據存儲、合并和查詢機制。本文介紹的最佳實踐并非孤立存在而是相輔相成。精心選擇的ORDER BY子句通常能使跳躍索引 (skipping indexes) 更為高效。恰當的數據類型能夠減輕物化視圖和投影的工作負擔。明智的分區(qū)策略能讓 ReplacingMergeTree (ReplacingMergeTree) 和基于 TTL 的過期策略 (TTL-based expiration) 有序運行。優(yōu)化數據攝取過程能保持健康的數據分片數量進而確保FINAL操作的執(zhí)行效率。本文中貫穿使用的 Amazon reviews 數據集基準測試表明這些并非微不足道的提升選擇正確的主鍵能將掃描數據量減少 347 倍正確的數據類型能將存儲空間削減 12% 并將查詢時間縮短 50%不必要的分區(qū)可能導致查詢速度降低 46 倍而字典查找的性能可比常規(guī)連接快 3 倍。這些都是純粹源于設計決策而非硬件升級所帶來的數量級差異。如果你是 ClickHouse 的初學者應重點關注前兩點主鍵設計和數據類型。它們的影響最為廣泛適用于你創(chuàng)建的每個表。在此基礎上在查詢需要時添加跳躍索引僅在有明確理由時進行分區(qū)并根據具體用例需求采用物化視圖和 ReplacingMergeTree。ClickHouse 會回饋那些深入理解其架構的用戶。你的 schema 和查詢與 ClickHouse 數據管理方式越是契合你的系統(tǒng)就將越快、越高效。在理想情況下這意味著你能夠攝取數十億行數據并以毫秒級的速度查詢它們。關于我們ClickHouse 是面向 AI 時代打造的高性能實時分析數據庫能夠以極致性能處理海量數據分析任務。憑借高并發(fā)、低延遲和云原生架構ClickHouse 廣泛應用于可觀測性、數據倉庫、實時分析及 AI 數據基礎設施等場景。我們致力于幫助企業(yè)在公有云平臺上構建安全、彈性且高性價比的實時分析與 AI 數據平臺加速釋放數據價值推動智能化創(chuàng)新與數字化轉型。目前Trip.com、DiDi、Meta、Sony、Netflix、Deutsche Bank、Sierra、Cloudflare 等全球領先企業(yè)均在使用 ClickHouse 支撐其關鍵業(yè)務和數據分析平臺。

相關新聞

2026年國內正規(guī)的嵌入式筒燈生產商聲譽前五名揭曉

2026年國內正規(guī)的嵌入式筒燈生產商聲譽前五名揭曉

老鐵們,今天咱們聊點干貨!搞裝修、開店、做工程的朋友都知道,嵌入式筒燈是燈具界的“小鋼炮”,但市面上魚龍混雜,選不對不僅浪費錢,還容易踩坑。我最近扒了2026年最新的行業(yè)數據,結合用戶口碑、…

2026/8/2 5:04:57 閱讀更多
攪拌設備機架各材質優(yōu)缺點詳解

攪拌設備機架各材質優(yōu)缺點詳解

結合豐享攪拌設備落地工況,針對以上五種常用機架材質,逐一拆解真實優(yōu)點、行業(yè)短板、適用邊界,解決選型低配生銹、高配浪費、材質用錯變形腐蝕等問題。1、普通噴漆碳鋼 Q235-B優(yōu)點:成本最低、焊接性能好、整體剛性穩(wěn)定、不易變形、…

2026/8/2 6:05:00 閱讀更多
BuildArena:基于物理仿真的LLM智能體工程基準測試平臺

BuildArena:基于物理仿真的LLM智能體工程基準測試平臺

1. 項目緣起:當大模型遇上物理世界,我們到底在測什么?最近兩年,大語言模型(LLM)在文本生成、代碼編寫、邏輯推理上的表現(xiàn)讓人眼花繚亂。但如果你問一個在建筑工地、工廠產線或者復雜設備裝配現(xiàn)場摸爬滾打多…

2026/8/2 6:05:00 閱讀更多
從玩具到生產力:構建有效AI智能體的四層能力與工程實踐

從玩具到生產力:構建有效AI智能體的四層能力與工程實踐

1. 從“玩具”到“生產力”:重新審視智能體構建最近和幾個做AI應用的朋友聊天,發(fā)現(xiàn)一個挺有意思的現(xiàn)象:大家一提到“構建智能體”,第一反應往往是去翻看某個熱門框架的文檔,或者直接套用LangChain、LlamaIndex這類工具…

2026/8/2 6:05:00 閱讀更多
3分鐘搞定!QQ空間歷史說說完整備份終極指南

3分鐘搞定!QQ空間歷史說說完整備份終極指南

3分鐘搞定!QQ空間歷史說說完整備份終極指南 【免費下載鏈接】GetQzonehistory 獲取QQ空間發(fā)布的歷史說說 項目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你是否曾想過,那些年發(fā)過的QQ空間說說,那些記錄青春的文字…

2026/8/2 0:04:01 閱讀更多
3分鐘搞定!QQ空間歷史說說完整備份終極指南

3分鐘搞定!QQ空間歷史說說完整備份終極指南

3分鐘搞定!QQ空間歷史說說完整備份終極指南 【免費下載鏈接】GetQzonehistory 獲取QQ空間發(fā)布的歷史說說 項目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你是否曾想過,那些年發(fā)過的QQ空間說說,那些記錄青春的文字…

2026/8/2 0:04:01 閱讀更多
AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O分配PCB板是應用材料(Applied Materials)公司生產的一款用于半導體設備的I/O信號分配電路板。該型號(0100-02186)的核心特點如下:專用于Endura等半導體工藝腔室。集成信號路由與分配功能。連接控制…

2026/8/2 2:51:21 閱讀更多
Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機是日本日清(Nissei)品牌的一款工業(yè)用三相異步電機,適用于自動化設備及通用機械驅動。該型號(FFMN-32L-10-T0 40AX)的核心特點如下:三相交流異步電動機。額定…

2026/8/2 2:52:49 閱讀更多