Clickhouse 架构详解

5 阅读14分钟

Clickhouse 架构详解

ClickHouse 是一款开源、高性能、列式存储的实时联机分析处理(OLAP)数据库,由俄罗斯 Yandex 公司研发。它彻底区别于 MySQL 这类行式事务数据库(OLTP),核心优势是海量数据秒级分析、超高压缩比、低存储成本、支持实时写入

本文摒弃晦涩的学术术语,用通俗化逻辑、底层原理、实战代码、运维规范全方位拆解 ClickHouse 架构,帮助读者从「会用」进阶到「懂原理、会调优、能落地」。

一、核心定位与底层设计思想(架构基石)

想要读懂 ClickHouse 架构,首先要理解它的设计初衷:专门解决「海量结构化数据的快速统计分析」问题,放弃了传统数据库的事务、高频更新能力,极致优化查询和写入性能。其核心设计思想有5个核心维度,也是它性能碾压传统大数据组件的关键。

1.1 列式存储:OLAP 场景的最优解

传统 MySQL 是行式存储,存储逻辑为「一行所有字段连续存储」,适合增删改查、单条数据查询;而 ClickHouse 采用纯列式存储,存储逻辑为「同一列的所有数据连续存储」。

通俗举例:一张用户行为表包含用户ID、姓名、访问时间、页面地址、停留时长5个字段。若需要统计「今日平均停留时长」,行式数据库需要读取整行5个字段数据,而列式数据库仅需读取「停留时长」一列数据,IO 开销直接降低 80% 以上。

同时,同列数据数据类型一致、特征相似,可实现超高压缩比(常见压缩比 3:1~10:1),大幅降低磁盘存储和读取开销。

1.2 向量化执行:批量数据计算,碾压逐行计算

普通数据库执行SQL时,是「逐行读取、逐行计算」,CPU 频繁切换指令,效率极低。ClickHouse 内置向量化执行引擎,默认将 8192 行数据封装为一个向量块,基于 CPU SIMD 指令实现「单指令批量处理多行数据」。

该设计让数据计算效率提升 3~5 倍,彻底消除了单行计算的 CPU 冗余开销,是其大查询秒级返回的核心原因之一。

1.3 稀疏索引:平衡索引效率与存储开销

传统数据库为每行数据建立索引,索引体积甚至超过数据本身,海量数据场景完全不可用。ClickHouse 采用稀疏主键索引,默认每 8192 行(索引粒度 index_granularity)建立一个索引标记。

索引文件仅记录每8192行的主键最大值、数据磁盘偏移量,索引体积极小、加载极快。查询时先通过索引过滤无效数据块,再精准读取目标数据,完美平衡了索引查询效率和存储成本。

1.4 后台数据合并:有序存储优化查询

ClickHouse 支持高并发实时写入,写入时不会立即排序合并数据,而是批量生成小数据块,避免写入阻塞。后台线程会异步对小数据块进行合并、排序、去重、聚合,最终生成有序的大文件。

该设计实现了「高吞吐写入」和「有序高效查询」的双赢,也是 MergeTree 引擎的核心设计逻辑。

1.5 无锁架构+线程池复用

ClickHouse 核心读写逻辑采用无锁设计,避免多线程锁竞争开销;同时内置固定线程池,复用线程资源,杜绝频繁创建销毁线程的性能损耗,高并发场景稳定性极强。

二、ClickHouse 整体分层架构(全局总览)

ClickHouse 整体架构分为四层核心架构+辅助组件,从请求接入到数据存储层层解耦,结构清晰、职责单一,同时支持单机和集群两种部署模式。

2.1 整体四层核心架构

Clickhouse 整体分层架构.png

1. 接入层(访问层)

负责接收客户端请求,支持多种通用协议,适配各类业务场景。支持 TCP、HTTP 双协议,兼容 JDBC/ODBC、Python、Go、命令行客户端等各类接入方式,同时管理用户会话、权限校验、请求限流等基础能力。

2. 查询处理层(核心计算层)

整个架构的大脑,负责SQL的全流程处理,分为三个核心模块:

  • 解析器:校验SQL语法,将SQL语句解析为抽象语法树,剔除非法语句;
  • 优化器:自动优化SQL执行逻辑,例如裁剪无效列、下推过滤条件、优化聚合顺序、分布式查询分片;
  • 执行器:基于向量化引擎执行计算,分布式场景下负责跨节点任务调度、结果聚合。
3. 存储层(数据持久层)

ClickHouse 的核心底座,负责数据落地、索引管理、文件合并、冷热数据清理。核心为MergeTree 系列存储引擎,所有业务核心表均基于此系列引擎构建,其他引擎仅作为辅助。数据以分区文件、标记文件、索引文件的形式持久化在磁盘,支持数据压缩、分区管理、TTL 自动清理。

4. 集成层

负责与外部系统联动,支持 Kafka、MySQL、HDFS、S3 等数据源的实时同步、批量导入,同时支持数据导出、备份恢复、监控对接等扩展能力。

2.2 单机架构 vs 分布式架构

1. 单机架构

所有组件集成在单个节点,部署简单、运维成本低,适合中小数据量(千万级 ~ 亿级)、测试环境、小型业务分析场景。单机模式下无分片、无副本,数据读写均在本地完成。

2. 分布式架构(生产主流)

基于「分片+副本+协调」架构搭建集群,支撑十亿级、百亿级海量数据,支持高可用、水平扩容,是生产环境标准架构,核心概念如下:

  • 本地表:每个节点真实存储数据的物理表,仅当前节点可读写;
  • 分布式表:逻辑虚拟表,不存储数据,负责将SQL请求分发到所有分片本地表,聚合结果后返回客户端;
  • 分片:将数据均匀拆分到多个节点,实现读写负载分担、容量扩容;
  • 副本:每个分片部署多个副本节点,实现数据高可用,单节点故障不影响业务;
  • ZooKeeper:集群协调核心,负责副本数据同步、节点健康检测、分布式DDL同步、数据合并调度。

三、核心存储引擎:MergeTree 深度解析(架构核心)

存储引擎是 ClickHouse 的灵魂,而 MergeTree 是唯一支持生产核心业务的引擎,所有高性能、高可用能力均基于此实现。其他引擎(Memory、Buffer、CSV 等)仅用于临时数据、数据中转、外部导入。

3.1 MergeTree 核心特性

  • 支持实时高吞吐写入,支持秒级千万级数据写入;
  • 支持分区、主键索引、稀疏索引、数据压缩
  • 后台异步数据合并,自动整理碎片化数据;
  • 支持 TTL 自动过期清理冷热数据;
  • 支持副本高可用、分布式分片存储。

3.2 MergeTree 核心衍生引擎(生产常用)

原生 MergeTree 仅支持基础存储,官方基于其内核衍生出4个高频实用引擎,适配不同业务场景,附实战建表代码。

1. ReplacingMergeTree(去重引擎)

适用于存在重复数据、需要自动去重的场景(如用户行为重放、数据重试写入)。合并数据时,会根据版本字段保留最新一条数据,删除历史重复数据。

 -- 实战建表:用户访问日志去重表
 CREATE TABLE user_visit_log (
     user_id UInt64 COMMENT '用户ID',
     visit_time DateTime COMMENT '访问时间',
     page_url String COMMENT '访问页面',
     create_version UInt32 COMMENT '数据版本'
 ) ENGINE = ReplacingMergeTree(create_version)
 PARTITION BY toYYYYMM(visit_time) -- 按月分区
 ORDER BY (user_id, visit_time) -- 排序主键(去重依据)
 PRIMARY KEY (user_id)
 TTL visit_time + INTERVAL 30 DAY DELETE; -- 30 天自动清理冷数据
2. SummingMergeTree(预聚合引擎)

适用于指标统计场景,写入明细数据后,后台自动对指定字段求和聚合,查询时直接读取聚合结果,大幅提升统计查询速度。

 -- 实战建表:用户每日访问指标聚合表
 CREATE TABLE user_daily_metric (
     user_id UInt64,
     stat_date Date,
     click_count UInt32 COMMENT '点击次数',
     income Float64 COMMENT '收益金额'
 ) ENGINE = SummingMergeTree
 PARTITION BY toYYYYMM(stat_date)
 ORDER BY (user_id, stat_date)
 -- 自动聚合字段:click_count求和、income求和
 SUMMING COLUMNS (click_count, income);
3. AggregatingMergeTree(复杂聚合引擎)

支持计数、去重、最大值、最小值等复杂聚合,搭配物化视图可实现实时预计算指标,是大屏实时报表的核心方案。

4. MergeTree(原生基础引擎)

仅存储明细数据,无自动聚合、无自动去重,适用于无需预处理的原始日志存储场景。

3.3 MergeTree 数据存储结构

每张 MergeTree 表的数据会按「分区-数据块」分层存储,磁盘核心文件包含:

  • .bin 数据文件:存储真实的列数据,经过高压缩处理;
  • .idx 索引文件:稀疏主键索引,记录每8192行数据的主键和磁盘位置;
  • .mrk 标记文件:记录数据块偏移量,快速定位读取位置;
  • partition 分区目录:按时间/自定义字段分区,实现分区裁剪、批量清理。

四、SQL 查询执行全流程(通俗拆解)

以分布式集群查询为例,完整拆解一条SQL从请求到返回结果的全流程,帮助理解架构运行逻辑:

  1. 请求接入:客户端通过HTTP/TCP发送SQL查询请求,接入层完成权限校验、限流;
  2. SQL解析优化:解析器校验语法,优化器自动下推where过滤条件、裁剪无用列、生成分布式执行计划;
  3. 分布式调度:分布式表将查询任务分发到集群所有分片节点;
  4. 本地数据查询:各分片节点执行本地查询,通过稀疏索引过滤无效数据块,读取目标列数据;
  5. 向量化计算:执行器以向量块为单位完成过滤、聚合、排序计算;
  6. 结果聚合返回:协调节点汇总所有分片结果,合并去重、二次聚合后,返回最终数据给客户端。

五、适用场景与禁用场景(架构适配核心)

ClickHouse 的所有架构设计都为「海量数据实时分析」服务,场景适配是落地关键,用对场景性能翻倍,用错场景完全不可用。

5.1 核心适用场景

  • 实时日志分析:业务日志、服务器日志、网关日志海量存储与实时检索;
  • 用户行为分析:用户点击、浏览、下单行为明细存储、用户画像统计;
  • 实时数据大屏:电商交易额、UV/PV、设备监控指标实时统计展示;
  • 时序数据分析:物联网设备数据、监控指标、时序数据批量分析;
  • 离线批量分析:替代Hive,实现海量数据秒级交互式查询。

5.2 绝对禁用场景

  • 事务业务(OLTP) :不支持事务、行级锁,无法用于订单、支付、用户账号等需要强一致性的业务;
  • 高频更新/删除:不支持单行高频update/delete,批量更新性能极差;
  • 小数据量频繁查询:架构针对海量数据优化,小数据量场景优势不明显,资源开销高于 MySQL;
  • 关联复杂查询:多表大JOIN性能较弱,不适合复杂多表关联业务。

六、编程实战:核心常用代码示例

本节提供生产高频使用的可运行代码,涵盖建表、写入、查询、物化视图、分区管理核心操作。

6.1 基础建表(标准生产模板)

 -- 业务日志明细表(生产通用模板)
 CREATE TABLE business_log (
     log_id String COMMENT '日志唯一ID',
     app_name String COMMENT '应用名称',
     event_type String COMMENT '事件类型',
     user_id UInt64 COMMENT '用户ID',
     request_time DateTime COMMENT '请求时间',
     cost_time UInt32 COMMENT '请求耗时ms',
     error_msg Nullable(String) COMMENT '错误信息'
 ) ENGINE = MergeTree
 PARTITION BY toDate(request_time) -- 按天分区
 ORDER BY (app_name, event_type, request_time) -- 排序主键
 PRIMARY KEY (app_name, event_type)
 INDEX idx_cost_time cost_time TYPE minmax GRANULARITY 2 -- 二级索引
 TTL request_time + INTERVAL 15 DAY DELETE -- 15 天自动清理
 SETTINGS index_granularity = 8192;

6.2 批量数据写入(高性能推荐)

 -- 批量插入(单次写入 ≥ 1000 行,杜绝单行频繁写入)
 INSERT INTO business_log VALUES
 ('10001','order-service','pay_success',10086,now(),12,NULL),
 ('10002','order-service','pay_fail',10087,now(),56,'余额不足'),
 ('10003','user-service','login',10088,now(),8,NULL);

6.3 实时物化视图(预计算指标)

无需定时任务,写入明细数据自动聚合指标,实现实时大屏:

 -- 创建每日应用事件统计物化视图
 CREATE MATERIALIZED VIEW app_event_mv
 ENGINE = SummingMergeTree
 PARTITION BY toYYYYMMDD(request_time)
 ORDER BY (app_name, event_type, request_time)
 AS SELECT
     app_name,
     event_type,
     toDate(request_time) as stat_date,
     count(log_id) as event_total -- 事件总数
 FROM business_log
 GROUP BY app_name, event_type, stat_date;

6.4 常用运维SQL

 -- 查看表分区
 SELECT partition, name, rows, disk_size FROM system.parts WHERE table = 'business_log';
 ​
 -- 手动触发分区合并(紧急数据整理)
 OPTIMIZE TABLE business_log FINAL;
 ​
 -- 删除指定分区
 ALTER TABLE business_log DROP PARTITION '2026-05-20';

七、生产运维核心要点与性能调优

ClickHouse 的性能上限不仅由架构决定,更依赖规范的运维调优,本节总结生产核心运维规则与避坑点。

7.1 写入运维规范

  • 禁止单行写入:必须批量写入,单次写入1000~10000行,大幅减少小文件生成;
  • 高频写入使用Buffer引擎中转:短时超高并发写入,通过Buffer表聚合数据后批量落地,避免频繁合并;
  • 分区粒度合理:数据量千万级用天分区,亿级用小时分区,杜绝单分区数据过大。

7.2 性能调优核心技巧

  • 主键设计精简:ORDER BY 字段不宜过多,仅保留查询过滤高频字段,减少索引开销;
  • 开启数据压缩:生产默认启用LZ4 压缩,冷数据可开启ZSTD 高压缩算法,节省磁盘空间;
  • 查询条件下推:尽量在WHERE中过滤数据,减少聚合计算的数据量;
  • 避免大JOIN:优先通过预聚合、宽表设计规避多表关联。

7.3 高可用运维要点

  • 集群必须部署ZooKeeper,保障副本同步、故障自动切换;
  • 每个分片至少2个副本,杜绝单节点故障数据丢失;
  • 定时备份元数据与核心数据,定期清理过期分区、碎片化文件;
  • 集群所有节点时区、时间同步,避免时间分区查询异常。

7.4 常见坑点规避

  • ReplacingMergeTree 去重仅在数据合并后生效,实时查询可能存在重复数据,需加FINAL关键字;
  • 后台数据合并会占用CPU、磁盘IO,业务高峰期避免手动触发OPTIMIZE合并;
  • 分区数量不宜过多,单表分区数建议不超过 1000,避免元数据加载缓慢。

八、架构总结与生产最佳实践

ClickHouse 的核心架构优势可以总结为:列式存储降IO、向量化计算提速度、稀疏索引省资源、异步合并保吞吐、分布式架构撑容量,是目前开源领域性价比最高的实时OLAP数据库。

生产落地最佳实践:

  • 中小数据量采用单机部署,大数据量采用「分片+双副本+ZooKeeper」集群架构;
  • 核心业务全部使用MergeTree系列引擎,搭配物化视图实现指标预计算;
  • 严格适配场景,只做分析不做事务、只批量写入不做单行更新;
  • 通过分区、TTL、批量写入、预聚合四大手段,实现性能与运维的最优平衡。