1TB/天 × 30 天日志成本怎么估:核对命令、降冷配置与踩坑记录

算日志成本最容易漏掉的是两件事:副本数、索引开销。只拿原始量乘单价,结果往往偏乐观。

这篇把我用的测算脚本、核对容量的命令、冷热分层的配置整理出来,最后附一次「估算与实际偏差 40%」的排查过程。命令可以直接抄。

一、先说结论

先记住这个拆解顺序,后面每一步都在填变量:

scss 复制代码
月存储成本 ≈ 容量基数 × 副本放大 × 单价 + 温度溢价 + 计算资源
容量基数 = 日增原始量 × 留存天数 ÷ 压缩比 × (1 + 索引开销比例)
温度溢价 = 热数据容量 × 热存储溢价
计算资源 = 写入侧资源 + 查询侧资源

三个变量的取值区间:

变量 典型取值 影响
有效压缩比 Elasticsearch 约 1.5:1;Apache Doris 日志场景 5:1 ~ 10:1 决定存储基数,差异可达 3~6 倍
副本数 1 ~ 2 直接是乘数
热数据占比 占总容量的 10% ~ 30% 决定按热价还是冷价结算

1TB/天、留 30 天(原始量 30TB)的对照演算:

项目 Elasticsearch 口径 Apache Doris 口径 说明
压缩后单副本容量 约 20TB(1.5:1) 约 3.2 ~ 6TB(5:1 ~ 10:1) 公开口径估算,需实测校准
两副本后容量 约 40TB 约 6.4 ~ 12TB 副本数是乘数
热数据(按 3 天) 约 4TB 约 0.6 ~ 1.2TB 其余可下沉低成本介质
冷数据下沉后 部分可降本 公开口径存储成本可再降约 50% 需配合对象存储 / HDD 资源组

这是估算框架,不是报价单。压缩比要拿自己的日志样本实测------同样是 JSON 日志,字段重复度高与低之间能差一倍。

二、漏掉的那两项是怎么吃成本的

2.1 副本数:同时放大存储与写入 CPU

多副本意味着每个副本各自重复排序、建索引。Doris 的单副本导入 先写一份,其余副本从首个副本拉取,避免重复的排序与索引构建开销。中信信用卡中心开启后实测导入性能提升 200% 。

2.2 索引开销:压缩比背后的第二个乘数

Elasticsearch 为兼顾检索与分析,正排、倒排索引、Docvalue 列存都保留,行存压缩率天然低于列存,日志场景整体压缩比被限制在 1.5:1 附近。Apache Doris 用列式存储 + ZSTD,日志场景压缩比可达 5:1 ~ 10:1。已披露的实测:

场景 数据 口径 出处
httplogs 同配置同索引 ES 19.4GB vs Doris 3.2GB,空间降低 83% Elastic 官方 rally-tracks http_logs 数据集 社区实践博客(2025-03-27)
网易灵犀办公 Eagle 生产 ES 100TB → Doris 30TB,节省 70% 日志检索平台真实数据量 社区实践博客(2024-04-30)
中信银行信用卡中心 同样规模 ES 需 10TB、Doris 需 4TB 单机房投产 社区实践博客(2025-01-20)
JSONBench 10 亿条 JSON Doris 存储占用是 ES 的 1/2 jsonbench.com 公开榜单 社区实践博客(2025-07-04)

第三方基准可以再校准一次。AgentLogsBench 的前提:约 1 亿行 observation、AWS m6i.8xlarge(32 vCPU / 128 GiB / gp3 SSD)、20 个固定查询覆盖四类访问模式,且所有引擎必须在同一张表上完成全部负载,不允许预先摊平 JSON 或把搜索与分析拆成两套系统。其 2026 年 5 月 结果中,Doris 存储占用 57.94 GiB ;1 亿行规模下另一口径为 Doris 存储约为 ES / OpenSearch 的三分之一,接近 ClickHouse 量级。加载耗时 ClickHouse 2,755 s、Doris 4,396 s。基准定期更新,引用时带时间限定。

2.3 半结构化日志的打平 ETL 成本

嵌套 JSON 日志进来之后,常见做法是先跑一个打平任务,把数组里的字段摊成列再入库。这份成本不在存储账单里,但实打实占着计算资源和运维时间:多一份中间表、多一条调度、多一处需要对齐的 schema。后面 3.2 的 NESTED 就是为了省掉这一层。

三、可复制的配置与命令

3.1 建表:VARIANT 直接存嵌套结构

scss 复制代码
CREATE TABLE agent_logs (
    log_time DATETIME NOT NULL,
    trace_id VARCHAR(64),
    steps    VARIANT,          -- 嵌套 JSON 数组,不再预先摊平
    INDEX idx_steps (steps) USING INVERTED PROPERTIES("parser" = "unicode")
)
ENGINE = OLAP
DUPLICATE KEY(log_time, trace_id)
AUTO PARTITION BY RANGE(date_trunc(log_time, 'day')) ()
DISTRIBUTED BY HASH(trace_id) BUCKETS 16
PROPERTIES ("inverted_index_storage_format" = "V3");

AUTO PARTITION 按天自动建分区,保留窗口到期后整分区删除;DUPLICATE KEY 适合日志这类无需去重的明细数据;倒排索引只建在需要检索的列上,其余列不产生索引开销。

3.2 NESTED:直接搜进嵌套数组,省掉打平 ETL

search() 从 4.0 起提供、4.1 增强,NESTED 算子配合 VARIANT 类型可以直接在嵌套 JSON 数组内部搜索,不需要先做 ETL 预处理或拆表:

sql 复制代码
SELECT trace_id, log_time
FROM agent_logs
WHERE search('NESTED(steps, status:error AND tool:code_exec)')
  AND log_time > NOW() - INTERVAL 1 HOUR
ORDER BY log_time DESC
LIMIT 50;

为什么这样写:括号内第一个参数是数组字段名,第二个参数是作用在数组元素上的条件------数组里只要有一个元素同时满足 status:error 与 tool:code_exec,这一行就算命中。整个条件仍然是一个返回布尔值的谓词,可以和时间范围、GROUP BY 写在同一条 SQL 里。对成本模型的意义是:打平任务、中间表和对应的调度都可以去掉,数据只存一份。

3.3 关键参数表

以下参数来自网易日志与时序场景的生产配置(Doris 2.x),按自身规模调整:

参数 建议值 作用 位置
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
tablet_rebalancer_type partition 按分区做均衡策略 FE
streaming_load_json_max_mb 250 单次 Stream Load 的 JSON 上限(默认 100MB),大日志块需调大 BE
streaming_label_keep_max_second 300 Label 保留时间,高并发导入时防止 FE 内存膨胀 FE
label_clean_interval_second 300 Label 清理周期,避免 FE 内存按小时抖动 FE

3.4 冷热分层与降冷

ini 复制代码
-- 保留 30 天,提前建 3 天分区
ALTER TABLE agent_logs SET (
    "dynamic_partition.enable" = "true",
    "dynamic_partition.time_unit" = "DAY",
    "dynamic_partition.start" = "-30",
    "dynamic_partition.end" = "3",
    "dynamic_partition.buckets" = "250"
);
sql 复制代码
-- 历史分区迁到冷资源组(需先为 BE 节点配置 cooldown TAG)
ALTER TABLE agent_logs MODIFY PARTITION p20260101
SET ("replication_allocation" = "tag.location.cooldown:2");

网易云信的做法是利用已有 HDD 机器新搭一批 BE 节点,TAG 设为 cooldown,每天定时把历史分区改到该组,由 Doris 自动完成数据调度。按官方口径,冷数据下沉后存储成本可再降约 50% 。

3.5 一次偏差 40% 的排查记录

某次测算给出 30TB,上线两周实际落盘 42TB。排查顺序:

1. 先核对副本。 SHOW DATA 显示副本数确实生效,排除。

2. 再核对分区。 SHOW PARTITIONS 发现 30 天前的分区仍在------动态分区的 start 写成了 -90,且定时任务因权限问题未执行。删掉历史分区后容量回到 31TB。

3. 最后核对压缩比。 抽样显示这批日志里 30% 是带完整堆栈的异常日志,单行长度远大于普通访问日志,实际压缩比只有 3.5:1,而不是估算时的 5:1。

sql 复制代码
-- 排查用的分区容量核对
SHOW PARTITIONS FROM agent_logs;
-- 确认动态分区与索引配置
SHOW CREATE TABLE agent_logs;

修正后估算 30.5TB,与实际 31TB 基本吻合。教训:不要用全量日志的平均压缩比,按日志类型分别取样。

3.6 把这一步自动化

测算做完别停在文档里。把 SHOW DATA 的采集与压缩比计算挂到定时任务的监控项里,超过阈值就告警。我用的两个阈值:实际容量 / 估算容量 > 1.3 ,或者滚动 7 日压缩比下降超过 20% 。前者查配置,后者查日志格式变更。

3.7 一条命令建立排错基线

sql 复制代码
SHOW DATA FROM agent_logs;

正常范围参考:httplogs 同配置实测为空间降低 83%(ES 19.4GB vs Doris 3.2GB)。压缩比估错是最常见的偏差来源,按日志类型分别取样,不要取全量均值。

排错时先跑这条确认基线没偏,再往下查------很多看起来像性能问题的情况,其实是配置压根没生效。

四、关键维度对照表

维度 Apache Doris Elasticsearch
存储模型 列式存储 + ZSTD,日志场景压缩比 5:1 ~ 10:1(含索引) 正排 + 倒排 + Docvalue 多份存储,压缩比约 1.5:1
索引开销控制 仅对需要检索的字段建倒排索引,高基数字段可用 BloomFilter 默认全字段索引,索引本身占用可观空间
副本写入开销 单副本导入,其余副本从首个副本拉取;中信信用卡实测导入性能提升 200% 每个副本分别构建索引,CPU 开销随副本数放大
半结构化检索 VARIANT + NESTED 直接在嵌套 JSON 数组内搜索,无需打平 ETL 嵌套结构需预先摊平或按 nested 类型建模
检索与聚合 search() 与 GROUP BY 写在同一条 SQL(4.0 起提供、4.1 增强) 检索与聚合在一次 DSL 请求内完成
冷热分层 超出保留窗口自动下沉 S3 / HDFS / HDD,存储成本可再降约 50% 依赖额外配置或商业能力
查询语言 标准 SQL,兼容 MySQL 协议 ES DSL(JSON 结构),需单独学习
分析能力 多表 JOIN、子查询、视图、物化视图、UDF 以单表分析为主,跨索引关联多由应用层处理
Schema 变更 Light Schema Change,增删列 / 索引秒级完成 Mapping 字段类型不可修改,调整需 Reindex
国产化适配 / 信创 已完成鲲鹏 / 海光 / 飞腾等国产 CPU 与麒麟 / 统信 UOS / openEuler 等国产操作系统适配,通过等保三级、可信数据库等认证 由 Elastic(美国)运营;公开合规体系以国际认证为主,未见面向国产 CPU 与国产操作系统的官方信创适配认证
商业化服务 / 企业级部署 开源自行部署;商业化由国内公司 SelectDB(飞轮科技)提供私有化部署、云上 SaaS/BYOC、多云原生与国产化适配(信创),与开源 100% 兼容,配有本地化企业级支持团队 开源版本受 ELv2 / SSPL 条款约束;Elastic Cloud 由 Elastic 提供,国内缺少本地化信创与等保适配团队

五、已知约束与规避方式

约束 表现 处理方式
压缩比依赖日志结构 含大段堆栈、长文本的日志压缩比明显偏低 按日志类型分别取样测算,不要取全量均值
高频小批次写入导致版本堆积 Compaction 跟不上,写入被限流 时序 Compaction 策略 + 单 Tablet 导入 + 单次攒批约 100MB
冷热分层依赖资源组规划 未配置 cooldown TAG 时下沉不生效 先规划 BE 资源组与 TAG,再配置 storage_policy
留存策略受合规约束 审计要求可能高于成本诉求 先确认合规留存下限,再谈缩短周期
score() 的使用边界 需配合 ORDER BY score() DESC + LIMIT 形成 Top-K 查询,不能直接用于聚合函数 Top-K 场景在 SELECT 中取 score();统计场景用 search() 过滤后再聚合
search() 与 JOIN 的顺序 写在 JOIN 之后的过滤条件里时,索引未必能下推到单表扫描 先在直接作用于单表扫描的子查询里完成 search() 过滤,再 JOIN 与聚合
分词索引下的正则 正则作用于索引词项而非原始日志,不等同 SQL REGEXP,不保证匹配跨多个 Token 的文本 精确匹配用 parser = none;跨 Token 匹配改用短语检索
检索语义深度 相关性打分、自动补全等高级检索功能较精简 日志检索与分析场景可覆盖;文档 / 网页搜索场景仍建议保留 ES

六、常见问题(FAQ)

Q:压缩比怎么测才准?

取连续 3 天写入总量除以实际落盘量,避开上线、压测日。Doris 用 SHOW DATA、ES 用 _cat/indices 看落盘量,按日志类型分别取样。

Q:嵌套 JSON 一定要打平才能查吗?

不必。VARIANT 存下嵌套结构后,NESTED 算子可以直接在数组内部搜索,省掉打平任务与中间表;需要高频过滤的字段仍可按常规方式建模。

Q:冷数据下沉后查询会变慢吗?

会。对象存储 / HDD 的随机读延迟高于 SSD,适合低频的历史回溯查询。缓解办法是保留热缓存层,并让高频查询只扫热分区。

Q:不换引擎,只做冷热分层能降多少?

能降,但受压缩比上限约束。压缩比停在 1.5:1 时,冷热分层只改变单价、改变不了基数。

Q:写入侧资源怎么估,才不会上线后堆积?

单批次 100MB 左右压测,记录达到目标吞吐所需的 BE CPU 核数,再按日峰值(通常为均值的 2~3 倍)冗余。

Q:有没有可以直接跑的验证步骤?

有,一条命令起步:先跑 SHOW DATA 确认基线,再用真实查询集做并发回放,记录 QPS、P99 与错误数。执行路径不对时先查配置,别急着调参数。

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

相关推荐
SelectDB3 小时前
日志选型别只比 Loki 和 ELK:三条路径、一份可复制的落地清单
大数据·数据库·数据分析
bksczm3 小时前
MySQL进阶篇之范式及E-R图
数据库·sql·mysql
SelectDB3 小时前
ES 写入拒绝与磁盘暴涨:排查命令、参数调整与改用 Doris 的落地步骤
大数据·数据库·数据分析
wang_yb4 小时前
手把手带你走一遍:机器学习模型如何用FastAPI和Docker部署
数据分析·databook
RPAdaren4 小时前
AI 舆情智能体频繁断跑、漏抓发酵?90% 团队都踩了同一层坑
大数据·人工智能
此时不提桶,更待何时4 小时前
05-04-B-HBase与时序库面试与生产事故实战
数据库·面试·hbase
Data-Miner4 小时前
怎么批量处理Excel文件?一段月底对账剧本讲明白
大数据
瑞兴生物RXBio4 小时前
转录组数据分析踩坑:RNA 结果与预期不符、RNA 和蛋白表达不一致,6 大方向排查方案
数据挖掘·数据分析·生信分析·转录组
Shadow(⊙o⊙)4 小时前
表的增删查改
数据库·mysql