2. ClickHouse基础
市场数据监控系统对写入吞吐、查询延迟和数据保留策略有极高要求。ClickHouse 之所以能在行情快照、逐笔成交、指标聚合等场景中成为主流选择,核心在于三件事:列式存储带来的 I/O 裁剪、MergeTree 引擎提供的分区与排序能力,以及分布式架构支撑的水平扩展。理解这三者的协作方式,是后续容量规划的前提。
一、列式存储:为什么市场数据查询快
行式存储按整行连续写入,适合事务型点查;列式存储把同一列的值连续存放,适合“读少数列、扫大量行”的分析型查询。市场数据监控的典型查询是“某合约在某时间段内的最新价、成交量、买卖盘口”,只涉及少量列,却要扫描大量行,列式布局能显著减少磁盘读取量。
列式存储还带来两个直接收益:同列数据类型一致,压缩率远高于行存;按列独立读取,配合向量化执行,CPU 缓存命中率更高。对于逐笔成交这类高基数、低重复度的数据,压缩比通常仍能达到 5~10 倍,直接降低存储成本与 I/O 压力。
二、MergeTree引擎:分区、排序与合并
MergeTree 是 ClickHouse 最核心的表引擎家族。它把数据按分区键切分为多个 part,每个 part 内部按排序键有序存储,后台线程持续将小 part 合并为大 part。分区用于裁剪扫描范围,排序键用于加速范围过滤和主键索引定位,合并则控制 part 数量、维持查询效率。
市场数据场景中,常见的建表策略如下:
CREATE TABLE market.tick
(
exchange LowCardinality(String),
symbol LowCardinality(String),
ts DateTime64(3),
price Decimal64(4),
volume UInt64,
side Enum8('buy'=1, 'sell'=2)
)
ENGINE = MergeTree
PARTITION BY toYYYYMMDD(ts)
ORDER BY (exchange, symbol, ts)
TTL ts + INTERVAL 30 DAY DELETE
SETTINGS index_granularity = 8192;
这里分区键按天切分,便于按时间淘汰;排序键以交易所、合约、时间排列,使同一合约的时间范围查询能连续读取;TTL 自动清理过期数据,降低运维负担。需要强调的是,排序键顺序直接影响索引效率,应把过滤频率最高、基数适中的列放在前面。
三、分布式架构:分片与副本
单机 MergeTree 受限于磁盘与 CPU,当写入量或数据量增长时,需要引入分布式表。ClickHouse 集群由多个分片组成,每个分片可配置多个副本。分布式表本身不存数据,只负责把查询路由到各分片并汇总结果;本地表才是实际存储数据的载体。
| 组件 | 职责 | 市场数据场景要点 |
|---|---|---|
| 分片(Shard) | 水平切分数据,分散写入与查询压力 | 按交易所或合约哈希分片,避免热点 |
| 副本(Replica) | 数据冗余,提升可用性与读吞吐 | 至少 2 副本,保障行情不中断 |
| 分布式表 | 查询路由与结果聚合 | 写入可走分布式表,也可直写本地表 |
| ZooKeeper / ClickHouse Keeper | 协调副本一致性 | 副本表必须依赖,需独立规划 |
分布式查询的执行过程是:客户端查询分布式表,Coordinator 将查询下发到各分片,各分片在本地并行执行,最后汇总返回。若查询包含 GROUP BY 或 ORDER BY,聚合会在各分片先做局部聚合,再在发起节点做最终合并。因此,分片键选择不当会导致数据倾斜,某些分片成为瓶颈。
四、市场数据场景与常见误区
以行情监控为例,典型数据流是:采集端写入逐笔与快照,MergeTree 按天分区存储,物化视图实时聚合分钟级指标,监控面板查询分布式表获取最新状态。容量规划需要同时考虑原始数据增长、副本放大、合并临时空间以及 TTL 清理节奏。
常见误区有三类。第一,把分布式表当作普通表频繁点查,忽略网络聚合开销;第二,分区键粒度过细,导致 part 数量爆炸,合并跟不上写入;第三,只规划原始数据容量,忽略副本、合并临时空间和 TTL 删除延迟。复盘时应重点检查 part 数量、合并队列长度、各分片磁盘使用率是否均衡。
掌握列式存储、MergeTree 与分布式架构的协作关系后,下一步才能准确评估写入吞吐、查询延迟与存储成本之间的平衡点,为后续监控指标设计和容量模型打下基础。