公司真题库

【京东】ClickHouse 的写入和读取为什么快

91学AI·2026/7/20·8 阅读

考察点

这道题出自京东大数据开发一面。ClickHouse 是实时数仓服务层的热门组件,面试官想确认你理解它快的根本原因,而不是只会说"列式存储所以快"。完整的答案要读写两侧都覆盖:读侧讲列存、向量化执行、稀疏主键索引、分区裁剪;写侧讲 part 追加写、后台 merge、批量插入的要求。追问常往"为什么不适合高并发点查"、"为什么不擅长更新删除"、"稀疏索引为什么不存每行"走。

参考答案

读为什么快:四个机制叠加

第一是列式存储。分析查询通常只碰几十个字段里的三五个,列存只读需要的列,IO 量直接降一个数量级。同列数据类型一致,压缩率天然高(字典编码、DoubleDelta、Gorilla 这类时序专用编码叠上 ZSTD,日志数据常见 5-10 倍压缩),IO 进一步减少。对比行存:哪怕只要一个字段也得整行读出来。

第二是向量化执行。引擎不是一行一行处理,而是按列批量(一次几万行的数组)喂给 CPU,配合 SIMD 指令单条指令处理多个数据,还规避了虚函数调用和分支预测失败的开销。这是 ClickHouse 把 CPU 利用率压榨到极致的关键——它快不仅是 IO 少,计算本身也快。

第三是稀疏主键索引。ClickHouse 的主键不是 B+ 树,不给每行建索引。数据按主键排序存储,每 8192 行(一个 granule)记一条索引项。查"某个订单号"时:索引只有几万条,全载内存,二分定位到几个 granule,再把这几个 granule 扫一遍。用"多扫几万行"换"索引小到常驻内存",对分析型查询是划算的买卖——分析查询本来就是扫大片数据,精确到行的索引没有意义,还占存储和写开销。

第四是分区与分片的并行裁剪。表按时间分区,查询带时间条件时整分区裁剪;数据分布到多 shard,查询并行下推各 shard 再汇总。配合 projection、物化视图还能做预聚合加速。

写为什么快:LSM 的思路

ClickHouse 的写入本质是 LSM-tree 那套"追加写 + 后台合并"。一次 insert 生成一个独立的 part 目录(内部按列文件组织,写之前已在内存按主键排好序),全程顺序写磁盘,没有随机更新、没有锁竞争、没有 B+ 树页分裂。写完成即对外可见。

后台 merge 线程池持续把小 part 合并成大 part(MergeTree 名字的由来),合并过程去重(ReplacingMergeTree)、聚合(AggregatingMergeTree)都在这一步做。写路径因此极轻,单节点每秒几十万行写入很轻松。

这个设计有一个必须知道的使用约束:要批量写。每批几千到几十万行一次 insert,生成一个 part;如果单行单行高频 insert,会产生海量小 part,后台 merge 追不上,最终触发 "Too many parts" 错误拒绝写入。这是 ClickHouse 生产事故的头部原因。正确姿势是消费端攒批(Flink sink 设 batch 大小和 flush 间隔),或者用 Buffer 表/异步插入(async insert)兜底。

硬币的另一面:代价是什么

理解快的同时要理解它放弃了什么,面试官等的就是这个。一,不适合高频小批量写入,上面已讲。二,更新删除弱:UPDATE/DELETE 是 mutation,异步重写整列数据,很重;高更新频率要么用 ReplacingMergeTree/CollapsingMergeTree 靠 merge 时去重(但查询要 FINAL 或聚合兜底,有坑),要么这场景根本不该用 ClickHouse。三,点查 QPS 低:稀疏索引导致每次点查要扫整个 granule,且没有行级缓存,点查走 Redis/HBase 才对。四,join 弱:大表 join 会把右表广播或构建 hash 表,内存压力大,官方建议用大宽表替代 join——这也是为什么数仓喂给 ClickHouse 的都是 join 好的宽表。

在京东数仓场景里的位置

收个尾把场景带上:实时数仓里 Flink 把订单明细宽表攒批写入 ClickHouse,运营看板直接查;需要修正的聚合数据走 Doris;点查走 Redis。选型逻辑正是利用它"批量写、大范围扫、少更新"的甜蜜区,避开所有短板——组件没有绝对的好坏,只有场景匹配度。

可能的追问

  • ReplacingMergeTree 的去重有什么坑?去重只在后台 merge 时发生,merge 前同一主键可能查出多条;要查时 FINAL(慢)或按主键 group by 取最新版本,且 merge 时机不可控,不能作为强一致手段。
  • 为什么不用跳表/B+ 树给每行建索引?每行索引在亿级数据下索引本身几十上百 GB,放不下内存还得随机读,得不偿失;稀疏索引用扫描换索引体积,符合 OLAP 扫描为主的负载特征。
  • 分片键怎么选?让查询最常用的过滤条件(一般是时间 + 租户/业务线)能裁剪分片,同时数据分布均匀防热点;电商场景常按日期分区 + 按 city/类目 hash 分片。

评论 (0)

暂无评论,快来抢沙发吧!

91学AI

© 2026 91学AI · 按岗位学 AI 与大数据. All rights reserved.