精选·OLAP与存储

OLAP 数据导入方式与攒批:为什么小批量高频写入是毒药

91学AI·2026/7/13·7 阅读

考察点

考察对 OLAP 写入链路的工程理解:为什么这类引擎天生厌恶小批量高频写入,以及实际项目里用什么姿势导数据。面试官想听具体的批量参数、攒批手段和失败处理,而不是「用 Stream Load 导入」这种名词。追问常考 Exactly-once 怎么保证、Kafka 接入的链路设计。

参考答案

为什么必须攒批:存储模型决定的

列存 OLAP 引擎的写入都是「批次 = 一个存储单元」。ClickHouse 每次 INSERT 生成一个新 part,Doris 每个导入事务生成一批 segment。这些单元随后要靠后台合并(merge/compaction)消化掉。写入频率一高,小单元数量暴涨,合并线程追不上:ClickHouse 直接抛 Too many parts 拒绝写入,Doris 表现是 compaction score 飙高、查询版本数爆炸、最终导入被限流。

经验数值是:单次导入至少几万行、几十 MB 起步,写入频率控制在秒级以上间隔。点击流这种每秒几百条的数据源,直写 OLAP 就是灾难,必须在中间层攒批。

ClickHouse 的导入姿势

最常见三条路。一是客户端攒批:应用或 Flink 侧按「条数 + 时间窗口」双触发攒批(比如满 5 万条或满 5 秒),批量 INSERT。Flink 的 ClickHouse Sink 就是这么干的,注意 sink 并发度要压低,多个并发 sink 各自攒批等于变相高频写。

二是 Kafka 引擎 + 物化视图:ClickHouse 自己消费 Kafka,物化视图转发进 MergeTree。优点是链路短、ClickHouse 内部天然按 block 批量落盘;缺点是语义是 at-least-once,消费失败重试会重复,要么靠 ReplacingMergeTree 去重,要么业务容忍。

三是文件批量灌:离线场景直接 clickhouse-client 读 CSV/Parquet 文件导入,或者 INSERT FROM s3/hdfs,百万行秒级完成,比任何实时链路都快。

Doris 的导入姿势

Doris 的导入种类多,按场景对号入座。Stream Load 是实时主力:HTTP PUT 推 CSV/JSON 数据,BE 接收后分发写入,同步返回结果——同步语义是它和 CK 的重要区别,客户端拿到成功才算成功,适合 Flink 两阶段提交对接(Doris 官方 connector 基于 Stream Load 做到 Exactly-once)。Routine Load 订阅 Kafka 持续消费,省去外部 ETL。Broker Load 从 HDFS/S3 批量拉文件,走批处理。INSERT INTO SELECT 用于库内流转。

Doris 攒批和 CK 同理:Stream Load 单批次建议 1-10GB 之间(上限受 stream_load_default_timeout 和 BE 内存约束),频率每个表几秒一次。Flink 侧同样是 checkpoint 触发批量 flush,checkpoint 间隔就决定了写入节奏。

一致性与失败处理

导入链路的难点不在快,而在「失败了怎么办」。设计原则是让重试安全:ClickHouse 侧用幂等键 + ReplacingMergeTree,或者按批次标记分区、失败后整批替换;Doris 的导入天然有 Label 机制——每个导入任务带唯一 Label,同 Label 重复提交直接幂等返回,这是它做 Exactly-once 的基石,Flink 两阶段提交就是靠 Label 预提交 + checkpoint 确认。

另一个高频考点是「上游 Kafka 积压了怎么办」:答案不是调大写入频率(会加剧小批量问题),而是调大单批大小——积压时每个批次自然吃到更多数据,吞吐反而上升,这是攒批架构的自我调节特性。

离线大促导入的特别处理

历史数据初始化或大促补数,和实时链路完全不是一个打法:直接生成列存文件(Parquet)走文件导入最快;导入前把目标表的分区、分桶数规划好,避免导入中途触发大规模 tablet 迁移;ClickHouse 侧可以临时调大 merge 线程和 parts 阈值,导完再调回来。导完务必跑一轮 compaction/merge 观察,确认版本数回落再放量查询。

可能的追问

  • ClickHouse 报 Too many parts 怎么应急和根治?—— 应急:临时调大 parts_to_throw_insert 阈值、加大 merge 线程、手工 OPTIMIZE 促合并。根治:改上游攒批,把单次 INSERT 提到几万行以上、频率降到秒级。
  • Doris 怎么做到 Flink 写入 Exactly-once?—— Stream Load 的 Label 幂等 + 两阶段提交:checkpoint 前预提交(Label 预占),checkpoint 完成后确认;失败则用同 Label 重试,重复 Label 不会重复生效。
  • Routine Load 和 Kafka 引擎直连有什么取舍?—— 都省了外部 ETL。Routine Load 是 Doris 内部任务好管理;CK 的 Kafka 引擎要注意它是 at-least-once,且物化视图链路的失败排查较绕,量大时更倾向 Flink 中转攒批。

评论 (0)

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

91学AI

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