Jaeger ClickHouse 存储后端基准测试指南:1 亿 Span 数据集下的压缩率、写入吞吐与查询延迟

发布时间:2026/11/4 17:21:50

Jaeger ClickHouse 存储后端基准测试指南:1 亿 Span 数据集下的压缩率、写入吞吐与查询延迟 Jaeger ClickHouse 存储后端基准测试指南1 亿 Span 数据集下的压缩率、写入吞吐与查询延迟【免费下载链接】jaegerCNCF Jaeger, a Distributed Tracing Platform项目地址: https://gitcode.com/GitHub_Trending/ja/jaeger本篇指南完整解读 Jaeger 官方仓库中 BENCHMARKING.md 记录的 ClickHouse 存储后端基准测试在 1000 万 Span100 万 Trace真实数据集上该后端取得了 8.6x 的数据压缩率、约 5.2 万 spans/sec 的写入吞吐以及毫秒级服务/操作检索和百毫秒级按 Trace ID 取数的查询延迟。读完本文你将理解这些数字背后的表结构与索引设计、掌握复现基准测试的方法并学会如何为你的 ClickHouse 集群预估容量与查询性能。基准测试概览本基准测试面向 Jaeger 新一代存储架构internal/storage/v2中的 ClickHouse 存储后端internal/storage/v2/clickhouse。它回答了一个关键问题当 ClickHouse 作为 Jaeger 的追踪数据仓库时在海量 Span 数据下能获得怎样的存储效率与查询性能测试结果分为三部分维度关键结果压缩率spans 表 5.99 GiB 未压缩数据被压缩至 722.09 MiB压缩比 8.6x写入吞吐1000 万 Span 总计耗时 191.8 s平均 52,129 spans/sec查询延迟服务/操作检索 3–4 msTrace ID 取数 101 ms属性搜索 1,769 ms以下各节将结合仓库源码逐项解读这些数字的由来与含义。测试环境与数据集测试环境基准测试在一台 Oracle Cloud 的 VM.Standard2.4 实例上执行硬件配置如下组件详情VMOracle Cloud VM.Standard2.44 OCPUsIntel Xeon Platinum 8167M内存60 GB磁盘47 GB 块存储操作系统Oracle Linux 9ClickHouse26单节点需要注意这是单节点部署4 个 vCPU 的规格意味着基准结果反映的是中小型实例上的性能表现生产环境通过水平扩展多节点分片/副本可获得更优吞吐。数据集参数值Trace 总数1,000,000每个 Trace 的 Span 数101 个父 Span 9 个子 SpanSpan 总数10,000,000服务数10分区数按天10每个 Span 的属性数11分布于 97 个不同 key、1000 个不同值数据集覆盖了 10 天时间窗口对应 spans 表PARTITION BY toDate(start_time)的按天分区设计见 create_spans_table.sql。97 个属性 key 与 1000 个属性值的规模对属性元数据缓存与类型化属性查询构成真实压力。存储压缩率8.6x 从何而来实测结果指标值未压缩大小5.99 GiB压缩后大小722.09 MiB压缩比8.6x压缩率主要来自三个设计选择列式存储天然压缩友好ClickHouse MergeTree 按列压缩同类数据如service_name聚集在一起重复值压缩效率极高。类型化属性数组Jaeger 的 ClickHouse 后端没有像 OTel-contrib 实现那样把所有属性值统一转成字符串而是将 key/value 拆分并按类型分列存储——bool_attributes、double_attributes、int_attributes、str_attributes、complex_attributes各自使用Array(Bool)、Array(Float64)、Array(Int64)、Array(String)等列见 create_spans_table.sql。同类型数值列可比混合类型字符串列获得更好的压缩比。复合类型 JSON 序列化slice/map 等复杂类型统一序列化为 JSON 字符串存入complex_attributes避免深层嵌套结构的存储开销。从源码看表结构spans 表是追踪数据的主表其核心设计create_spans_table.sqlCREATE TABLE IF NOT EXISTS spans ( id String, trace_id String, ... start_time DateTime64(9), duration Int64, bool_attributes Nested (key String, value Bool), double_attributes Nested (key String, value Float64), int_attributes Nested (key String, value Int64), str_attributes Nested (key String, value String), complex_attributes Nested (key String, value String), events Nested (...), links Nested (...), ... INDEX idx_trace_id trace_id TYPE bloom_filter GRANULARITY 1, INDEX idx_duration duration TYPE minmax GRANULARITY 1 ) ENGINE MergeTree PARTITION BY toDate(start_time) ORDER BY (service_name, name, toDateTime(start_time))两个跳过索引直接服务于基准测试中的两类查询idx_trace_idbloom_filter让「按 Trace ID 取数」不必全表扫描idx_durationminmax让「按持续时间范围搜索」能快速裁剪数据块。排序键(service_name, name, toDateTime(start_time))则与「按服务搜索」「按操作搜索」的查询模式对齐。这一表结构与 OTel-contrib 的 ClickHouse exporter 相比有显著差异详见 README.md 中的说明。写入吞吐52,129 spans/sec指标值Span 总数10,000,000总写入耗时191.8 s吞吐量52,129 spans/sec写入路径的高吞吐依赖两个关键机制ch-go批量插入写操作使用ch-go的chpool以 batch 模式写入见 README.md。在 writer.go 中WriteTraces首先PrepareBatch将ResourceSpans → ScopeSpans → Spans逐层遍历后逐条batch.Append最后一次性batch.Send将网络往返次数压缩到最低。按类型拆分属性列dbmodel.ToRow将 span 的属性、Resource 属性、Scope 属性、Event 属性、Link 属性分别转换为类型化 key/value 数组见 dbmodel/from.go写入时直接对齐InsertSpan语句中 60 余个占位符列见 sql/queries.go避免了类型转换开销。写入侧的连接专门用于写、不开启埋点插桩见 writer.go 注释防止追踪自身产生递归写入流量。查询延迟Retrieval 与 Search 两个维度基准测试将查询分为两类每个查询运行 3 次取平均Retrieval Queries按 ID/名称直取查询平均耗时获取服务列表Retrieve services3 ms获取操作列表Retrieve operations4 ms按 Trace ID 取 TraceGet trace by ID101 ms服务与操作检索的毫秒级延迟来自两张物化视图表services create_services_mv.sql物化视图配合SELECT name FROM services GROUP BY name查询queries.gooperations create_operations_mv.sql物化视图按service_name与span_kind过滤queries.go。按 Trace ID 取数耗时 101 ms由SelectSpansByTraceIDSELECT ... FROM spans s WHERE s.trace_id ?见 queries.go配合idx_trace_idbloom_filter 索引支撑。取数后还需在 Go 侧完成 span 行反序列化与 trace 组装reader.go。Search Queries带过滤条件的搜索查询平均耗时按服务搜索37 ms按操作搜索38 ms按持续时间范围搜索43 ms按时间戳范围搜索47 ms按属性搜索1,769 ms按全部条件组合搜索139 ms搜索路径先执行buildFindTraceIDsQuery构造「查 Trace ID」的子查询再用buildFindTracesQuery将子查询嵌入WHERE s.trace_id IN (...)外层取数query_builder.go。内部子查询基于SearchTraceIDsBaseWHERE 11便于无条件下追加AND条件见 queries.go并以trace_id_timestamps表 JOIN 补全 Trace 的起止时间queries.go。属性搜索1,769 ms显著慢于其他查询原因是属性查询需要对嵌套数组执行arrayExists((key, value) - key ? AND value ?, ...)的逐行扫描query_builder.go且需依次检查 span、resource、scope、events、links 五个层级buildSimpleAttributeConditionquery_builder.go。若读者关注属性检索性能这是当前实现的主要瓶颈所在。值得注意组合全部条件反而快于单独属性搜索139 ms vs 1,769 ms额外的过滤条件服务名、时间范围等借助排序键与分区裁剪大幅缩小了需要扫描的 Span 集合。这提示一个实用调优思路——属性搜索应尽量与其他条件组合使用。字符串属性的类型还原机制基准数据集中 11 个属性/span 分布于 97 个 key字符串属性的查询走buildStringAttributeCondition路径查询服务以AsString()形式传入所有属性后端需要查 attribute_metadata 表获知该 key 实际存储的类型bool/double/int/str/bytes/map/slice与层级resource/scope/span再通过strconv反向解析为正确类型生成条件query_builder.go。属性元数据本身带有 LRU 缓存TTL 与容量分别由配置项attribute_metadata_cache_ttl默认 1h与attribute_metadata_cache_max_size默认 1000控制config.go。复现基准测试原文档给出如下复现指引See the clickhouse-benchmarking repository for setup and reproduction instructions.该仓库为 Jaeger 团队成员的独立 benchmark 工程包含环境搭建、数据集生成、schema 初始化与查询脚本。在复现前你需要先在本仓库中启动 ClickHouse 存储后端。最直接的方式是使用官方示例配置 config-clickhouse.yaml它演示了jaeger_storage扩展的完整配置extensions: jaeger_storage: backends: some-storage: clickhouse: addresses: - localhost:9000 database: jaeger auth: basic: username: default password: password create_schema: true其中create_schema: true会执行本仓库 sql 目录 下全部建表与物化视图脚本spans、services、operations、trace_id_timestamps、attribute_metadata、dependencies 及其物化视图这些 SQL 通过go:embed嵌入二进制queries.go。关键配置项ClickHouse 后端的完整配置项定义在 config.go复现基准时可重点关注配置项默认值说明protocolnative连接协议可选native/httpaddresses必填ClickHouse 服务器地址列表databasejaeger目标数据库auth.basic无用户名/密码认证create_schemafalse启动时自动建表default_search_depth1000未指定 limit 时的默认搜索深度返回的 Trace ID 上限max_search_depth10000允许的最大搜索深度attribute_metadata_cache_ttl1h属性元数据缓存 TTL0 表示永不过期attribute_metadata_cache_max_size1000属性元数据缓存条目上限0 表示禁用ttl0Span 数据自动删除的 TTL0 表示禁用配置校验逻辑config.go要求ttl必须为非负且为整秒数default_search_depth与max_search_depth必须为正数否则每次搜索都会返回空结果。搜索深度限制在 query_builder.go 中强制执行——超过max_search_depth的查询会被直接拒绝。数据生成与写入复现 1000 万 Span 的数据集有两种途径外部 benchmark 仓库按其setup/native目录指引生成原生 schema 与数据集原文档推荐路径。仓库自带工具使用 cmd/tracegen 生成追踪数据并经 OTLP 接收器写入 Jaeger写入路径会经过 writer.go 的批量插入逻辑与基准测试的写入侧行为一致。读基准测试时应关注的要点环境差异4 vCPU/60 GB 单节点配置下测得的结果在更大规格或集群部署下数字会变化请勿直接外推为生产容量承诺。属性搜索是当前热点1,769 ms 的属性单独搜索耗时明显高于其他查询若你的业务大量依赖属性过滤应结合attribute_metadata缓存命中率与查询组合方式做针对性优化。压缩率支撑成本评估8.6x 压缩比意味着 5.99 GiB 原始数据仅需约 0.7 GiB 存储可作为磁盘容量规划的下限参考。复现的起点在仓库内从 config-clickhouse.yaml 出发搭建环境再运行 benchmark 仓库的 schema 与查询脚本即可得到可对比的数字。参考源码索引后端入口与配置factory.go、config.go建表与物化视图 SQLsql 目录写入实现tracestore/writer.go读取实现tracestore/reader.go查询构造器tracestore/query_builder.go类型化属性映射tracestore/dbmodel/from.go指标RED 指标存储metricstore/reader.go官方部署配置示例cmd/jaeger/config-clickhouse.yaml、cmd/jaeger/config-spm-clickhouse.yaml官方集成测试cmd/jaeger/internal/integration/clickhouse_test.go本基准测试文档BENCHMARKING.md【免费下载链接】jaegerCNCF Jaeger, a Distributed Tracing Platform项目地址: https://gitcode.com/GitHub_Trending/ja/jaeger创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/11/5 14:10:30

ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 14:10:30

UART接口24位ADC搭配RS485,解决远距离温度监控难题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 14:10:30

UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 13:55:19

GD32E10x官方例程入门:从GPIO点灯到串口调试

简介:这份GD32E10x系列官方例程面向嵌入式硬件与单片机开发者,基于ARM Cortex-M3内核,汇集兆易创新GD32E10x的示例代码,适合工业控制、消费电子、通信设备等场景的学习、验证与二次开发。压缩包共935个文件,约11.16MB&…

2026/11/5 13:50:18

基于Django的运维平台实战:资产、发布、巡检、告警一体化

简介:这份资源是一套基于Django框架开发的运维平台源码,面向具备Python基础、希望了解Web运维系统实现思路的开发者与运维人员,可用于学习主机管理、服务监控、日志查看、任务调度、权限控制、资源统计、脚本执行与故障告警等常见运维模块的落…

2026/11/5 13:25:11

基于ADS122U04IPWR与STM32F427ZI的工业测温方案设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑