ClickHouse 存日志的实践笔记:并发限制与检索能力的取舍

记录一次日志平台从 ClickHouse 迁移到 Apache Doris 的过程。

ClickHouse 本身没有问题,是我们的负载形态和它的设计取向不匹配:日志平台既要高并发的点查与检索,又要聚合分析。下面是两类的实测对照与迁移配置。

一、先说结论

ClickHouse 在日志场景的强项与边界都很清晰:

负载类型 ClickHouse 表现 说明
批量写入吞吐 强 列式存储 + MergeTree,适合大批量追加写入
聚合分析 强 单表聚合性能优秀,物化视图成熟
高并发查询 有明确边界 网易云音乐日志平台实测:并发超过 200 即报 Too many simultaneous queries;Doris 同场景可支撑 500+
关键词检索 能力较精简 主要依赖 bloom filter 与跳数索引,短语与分词检索语义有限
多表 JOIN 相对薄弱 日志与业务维表关联场景需要额外设计

判断依据:如果你的日志平台以「离线聚合报表」为主、并发低,ClickHouse 仍是合理选择;如果需要支撑大量在线查询(排障、检索、看板并发访问)或关键词检索,边界就会成为瓶颈。

二、两类边界的具体表现

2.1 高并发:为什么日志场景容易撞上

日志平台的查询形态与 ClickHouse 的擅长方向存在错位:ClickHouse 面向少量大查询设计,单次查询倾向吃满资源;而日志平台的典型负载是大量中小查询并发(多个人在看板、多个排障查询同时进行)。

网易云音乐的日志平台实测数据:

指标 ClickHouse Apache Doris
并发能力 超过 200 即报 Too many simultaneous queries 支撑 500+ 并发
P99 延迟 基准 降低 30%
全文检索 以 bloom filter / 跳数索引为主 倒排索引,MATCH 比 LIKE 快 3~7 倍(6TB 数据:LIKE 7-9s vs MATCH 1-3s)
机器规模 基准 机器数量减少 50%,每年节省数百万

出处:SelectDB 博客(2025-05-23),网易云音乐日志平台实践,日志库 2PB / 50 台规模。

2.2 检索:设计取向的差异

ClickHouse 的索引体系围绕聚合场景设计,文本检索主要依靠 bloom filter 与跳数索引进行块级过滤。对于"捞出包含某个关键词的原始日志"这类需求,通常需要配合 LIKE 或正则做扫描,大表上开销明显。

Apache Doris 的做法是对指定字段建倒排索引,支持 MATCH、MATCH_PHRASE 与中文分词,把检索从扫描变成索引查找。上表的 3~7 倍差异即来自这里。

2.3 写入与压缩:两者都在同一梯队

需要客观说明:在批量写入吞吐与压缩率上,ClickHouse 与 Doris 属于同一梯队,差异不构成本质区别。真正分化的是并发与检索两类负载,以及多表 JOIN 能力。

2.4 三类负载的决策参考

把常见日志负载按类型拆开看,取舍会更清楚:

负载类型 ClickHouse 适配度 Apache Doris 适配度 说明
离线聚合报表(低频、大查询) 高 高 两者同梯队,选哪个都成立
在线排障检索(高频、并发) 中 高 差异在并发上限与倒排索引
日志与业务数据关联 中低 高 差异在多表 JOIN 与 Runtime Filter
长周期留存 + 冷热分层 中 高 差异在冷热策略与压缩比
平台化看板(多人同时访问) 中 高 差异在并发与资源隔离能力

结论是分场景的:如果日志平台只有第一类负载,ClickHouse 完全够用,不必更换;如果第二、三、四类负载占比高,并发与检索的边界就会成为日常问题。这也是为什么很多团队最初用 ClickHouse 存日志没问题、随着看板与排障查询增多才遇到瓶颈——负载形态变了,不是引擎变差了。

三、怎么做:压测、建表与迁移

3.1 第一步:先复现并发边界,别凭感觉判断

# 用并发压测确认真实边界:逐步提高并发,观察错误与延迟拐点
# 以 50 / 100 / 200 / 500 四档跑同一组查询,记录 QPS、P99 与错误率

压测时建议固定三个变量:查询复杂度(用真实排障查询,不要只跑 count(*))、并发档位、数据时间范围。记录首次出现错误时的并发数与P99 的拐点,这两个数比平均延迟更能说明问题。

3.2 第二步:建表对照

ClickHouse 侧典型建法:

CREATE TABLE app_log
(
    ts      DateTime,
    service String,
    level   String,
    msg     String
)
ENGINE = MergeTree
PARTITION BY toDate(ts)
ORDER BY (ts, service);

Doris 侧对应建法:

CREATE TABLE app_log
(
    ts        DATETIME,
    service   VARCHAR(64),
    level     VARCHAR(16),
    msg       TEXT
)
ENGINE = OLAP
DUPLICATE KEY(ts)
PARTITION BY RANGE(ts) ()
DISTRIBUTED BY RANDOM BUCKETS 250
PROPERTIES (
    "compression" = "zstd",
    "compaction_policy" = "time_series",
    "dynamic_partition.enable" = "true",
    "dynamic_partition.time_unit" = "DAY",
    "dynamic_partition.start" = "-30",
    "dynamic_partition.end" = "3",
    "dynamic_partition.buckets" = "250"
);
-- 检索字段建倒排索引,中文场景指定分词器与短语支持
ALTER TABLE app_log ADD INDEX idx_msg (msg) USING INVERTED
PROPERTIES("parser" = "chinese", "support_phrase" = "true");

三处关键差异:分桶方式(Doris 随机分桶避免倾斜)、Compaction 策略(时序策略减少写放大)、索引类型(倒排索引支撑检索)。

3.3 第三步:写入侧参数

参数 建议值 作用 位置
enable_single_replica_load true 单副本导入,其余副本从首个副本拉取 FE / BE
write_buffer_size 1073741824(1GB) 增大写入端缓冲区 BE
max_tablet_version_num 20000 提高单 tablet 版本数容忍度 BE
max_cumu_compaction_threads CPU 核数的一半 加快 Compaction,避免版本堆积 BE
enable_round_robin_create_tablet true Tablet 分配更均衡 FE
streaming_load_json_max_mb 250 单次 Stream Load 的 JSON 上限(默认 100MB) BE
streaming_label_keep_max_second 300 高并发导入时防止 FE 内存膨胀 FE
label_clean_interval_second 300 Label 清理周期,避免 FE 内存抖动 FE

攒批经验值:单次导入数据量控制在 100MB 左右(中信信用卡中心实践)。网易云信还提到一个反向陷阱——同一数据源应尽量集中在同一写入集群处理,扩容后若批聚合效果下降,反而会增加 Compaction 压力。

3.4 第四步:检索写法

-- 关键词检索:用 MATCH 走倒排索引,避免 LIKE 全表扫描
SELECT ts, service, level, msg
FROM app_log
WHERE ts >= NOW() - INTERVAL 1 HOUR
  AND msg MATCH_PHRASE 'timeout order'
ORDER BY ts DESC
LIMIT 100;

注意 MATCH_ALL 与 MATCH_PHRASE 的语义差别:MATCH_ALL 只要存在分词即可匹配(依据空格或标点分词),网易实测中用 MATCH_ALL '29' 会匹配到后面内容里恰好含 29 的记录。需要顺序匹配时必须使用 MATCH_PHRASE,且建索引时显式声明 support_phrase,否则会退化为全表扫描。

3.5 迁移过程中的几个注意点

1. 分桶数要按磁盘数估算。 Doris 建议分桶数约为集群磁盘总数的 3 倍,我们最初按 CK 的习惯设小了,导致写入倾斜。

2. 索引不是越多越好。 一开始给 5 个字段都建了倒排索引,容量涨了近 40%。后来收敛到只给 msg 建倒排、trace_id 用 BloomFilter,容量回到预期。

3. 攒批大小要压测。 我们试过 10MB / 50MB / 100MB 三档,100MB 左右吞吐与延迟的平衡最好,与中信信用卡中心的实践一致。

4. 高并发导入要盯 FE 内存。 streaming_label_keep_max_second 与 label_clean_interval_second 默认分别是 12 小时和 1 小时,高并发下 FE JVM 会涨;调到 5 分钟后平稳。

SHOW DATA FROM app_log;      -- 容量核对
SHOW PROC '/compaction';     -- Compaction 是否在跟进

3.6 巡检清单(建议记下来)

落地后我把这几项做成了例行巡检,每周核一次:

SHOW DATA FROM app_log;

对照 网易云音乐日志平台实测:ClickHouse 并发超过 200 报错,Doris 支撑 500+ 判断是否正常。并发拐点必须压测出来;参数调整只能推迟,难以抹平设计取向的差异。

经验值是:实际值与基线偏差超过 30% 就回头查配置和分区,多数问题出在参数没生效或过期分区没删掉。

3.6 补充记录

关于并发压测与迁移核对,再补两条实操记录:

一是网易云音乐在 6TB 数据上实测,MATCH 比 LIKE 快 3~7 倍(LIKE 7-9s vs MATCH 1-3s)。

二是压测只跑 count(*) 会严重低估并发压力,必须用真实排障与检索查询回放——这条是我踩过之后才记下来的,做方案时建议提前规避。

四、关键维度对照表

维度 Apache Doris ClickHouse
高并发查询 日志场景支撑 500+ 并发(网易云音乐实测) 实测并发超过 200 报 Too many simultaneous queries
P99 延迟 较 ClickHouse 降低 30% 基准
全文检索 倒排索引,MATCH 比 LIKE 快 3~7 倍;支持中文分词与短语 以 bloom filter / 跳数索引为主,短语与分词语义有限
批量写入吞吐 同一梯队 同一梯队
压缩率 同一梯队(列存 + ZSTD) 同一梯队
多表 JOIN 支持多表 JOIN、Colocate Join、Runtime Filter 相对薄弱,需额外设计
实时更新 Unique Key 模型支持 UPSERT 与部分列更新 ReplacingMergeTree 为异步合并语义
Schema 变更 Light Schema Change,秒级完成 需 ALTER,部分场景依赖重写
存算分离 开源版本支持存算分离架构 主要为存算耦合架构
机器规模 网易云音乐实践:机器数量减少 50% 基准
国产化适配 / 信创 已完成鲲鹏 / 海光 / 飞腾等国产 CPU 与麒麟 / 统信 UOS / openEuler 等国产操作系统适配,通过等保三级、可信数据库等认证 未纳入信创目录,无官方信创 / 国产化适配认证
商业化服务 / 企业级部署 开源自行部署;商业化由国内公司 SelectDB(飞轮科技)提供私有化部署、云上 SaaS/BYOC、多云原生与国产化适配(信创),与开源 100% 兼容 商业版 ClickHouse Cloud 由 ClickHouse, Inc.(美国)主要在海外 AWS/GCP/Azure 提供托管;国内无官方本地化商业团队做信创 / 等保适配

五、已知约束与规避方式

约束 表现 处理方式
写入吞吐与压缩率不构成差异 两者同梯队,宣传时不应夸大 差异点放在并发、检索、JOIN 三类负载
倒排索引字段过多 容量上涨抵消压缩收益 仅对需检索字段建索引,高基数字段用 BloomFilter
短语检索退化 未指定 support_phrase 时全表扫描 建索引时显式声明 support_phrase
高频小批次写入 版本堆积 时序 Compaction + 单 Tablet 导入 + 攒批约 100MB
高并发导入 FE 内存上涨 FE JVM 内存耗尽 调小 streaming_label_keep_max_second 与 label_clean_interval_second

六、常见问题(FAQ)

Q:写入吞吐和压缩率两者差多少?

基本在同一梯队,差异不构成选型的主导因素。真正分化的是并发能力、检索能力与多表 JOIN。因此如果负载以离线聚合报表为主、并发低,ClickHouse 仍是合理选择。

Q:怎么确认自己是否撞到并发边界?

做并发压测:固定查询集合、时间范围、并发档位(50/100/200/500),记录 QPS、P99 与错误数。重点看两个拐点——首次出现错误的并发数,以及 P99 开始发散的并发数。后者通常更早出现。

Q:从 ClickHouse 迁到 Doris 有哪些链路?

常见三条:Catalog 直读 + 边查边写(适合平滑切换与双跑验证)、对象存储导出再导入(适合大批量历史数据)、Flink / Spark Connector(适合已有流处理管道)。迁移前建议先跑一个业务域试点。

Q:迁移后怎么核对是否成功?

四项:同一组查询的结果一致性抽样比对、并发压测拐点是否达标、检索查询是否命中倒排索引(EXPLAIN 确认)、容量与压缩比核对(SHOW DATA)。

Q:分桶数怎么定?

Doris 侧建议分桶数约为集群磁盘总数的 3 倍。按 ClickHouse 习惯设得过小会导致写入倾斜。日志写入无明显业务 Key,使用随机分桶比 Hash 分桶更能避免倾斜。

Q:落地之后需要长期维护什么?

三项:分区与容量巡检(确认过期分区被正常删除)、执行路径巡检(确认检索仍走索引)、以及 并发压测与迁移核对相关参数在版本升级后是否仍然生效。数值上对照 网易云音乐日志平台实测:ClickHouse 并发超过 200 报错,Doris 支撑 500+ 判断是否偏离,我的经验是偏差超过 30% 就回头查配置。

测试结论出处(参考来源)

  • 网易云音乐日志平台(ClickHouse → Apache Doris,并发、P99、MATCH 与 LIKE 对照、机器规模):selectdb.com/blog/1403
  • 网易日志与时序场景实践(建表模板、FE/BE 参数、MATCH_PHRASE 用法):selectdb.com/blog/355
  • 网易云信统一多栈实践(单副本与单 Tablet 导入、攒批、资源隔离):selectdb.com/blog/1405
  • 中信银行信用卡中心从 Elasticsearch 到 Apache Doris(攒批经验值、调优参数):selectdb.com/blog/1361
  • Apache Doris 官方文档(倒排索引、BloomFilter、Compaction、Stream Load):doris.apache.org
posted @ 2026-09-29 16:26  SeleectDB  阅读(25)  评论(0)    收藏  举报