可观测性OSS
前置条件
- 你的机器上已安装 clickhouse-local。请参阅 clickhouse-local 设置指南 了解如何开始使用。
你将构建的内容
Map 类型:键是动态的,并且因应用而异,但任意一行通常只包含其中少数几个。
在本快速入门中,你将使用 clickhouse-local 将来自 CSV file 的真实 OTel trace 数据加载到包含 Map(LowCardinality(String), String) 列的表中,并学习如何对 map 数据进行查询、过滤、聚合和优化。
下载示例数据
该数据集包含从一个演示微服务应用导出的 6,120 个 OTel trace span。每一行都包含
ResourceAttributes 和 SpanAttributes 两列,这两列中是以 JSON 映射形式存储的动态键值对。
将文件保存到一个便于引用的目录中,例如 ~/data/data-otel-traces.csv。下载 data-otel-traces.csv (2.9 MB)单行数据如下所示:创建表并加载数据
启动 现在使用 确认数据已成功加载:你应该会看到 6,120 行。
clickhouse-local,并创建下列表,其 schema 与 CSV 相匹配。
关键列是 ResourceAttributes Map(LowCardinality(String), String)——在键类型上使用 LowCardinality,因为 OTel attribute 键通常来自一个相对较小且会重复出现的集合。file 表引擎加载 CSV。请将路径改为你保存该文件的位置:查询数据
访问特定键 — 使用方括号语法从 map 中取出值。如果某一行中不存在该键,则会返回该值类型的默认值 (按 Map 值过滤 — 查找特定服务名称的所有 spans:检查某个键是否存在 —— 并非每个 查看数据集中出现的所有键 —— 有助于了解埋点产生了哪些内容:使用 ARRAY JOIN 将 map 展开成多行 — 让每个键值对各自成为一行,便于构建属性清单或为仪表盘提供数据:使用 查找错误 span 及其资源上下文 — 将常规列过滤条件与 Map 访问结合使用:
String 的默认值为空字符串) :span 都带有 Kubernetes 元数据。使用 mapContains 找出哪些 span 带有这些元数据:mapFilter 过滤 Map — 仅提取每个 span 中与 Kubernetes 相关的属性:使用 -Map 组合器对 Map 进行聚合
ClickHouse 的 现在使用 你也可以将它与其他组合器结合使用。例如,**为什么这对 OTel 很重要:**当你的 OTel collector 将按分钟统计的状态码明细写入 ClickHouse 时,
-Map 聚合组合器可让你将任意聚合函数应用到 Map 列上,并对每个键分别进行聚合。结果本身也是一个 Map——每个键对应一个条目,其中包含聚合后的值。这对 OTel 指标尤其有用,因为 counter 或 gauge 通常存储为 map 值。为便于演示,先创建一个小型指标表,其中每一行都将 HTTP 状态码计数记录为 Map(String, UInt64):sumMap 按服务汇总各状态码的计数:-Map 后缀可用于任何聚合函数,因此你同样可以轻松使用 minMap、maxMap 或 avgMap:sumMapIf 可以让你按条件聚合——这里仅对该服务已出现错误的分钟窗口求和:sumMap 可让你通过一次查询将其汇总为按小时或按天统计的总计——无需 ARRAY JOIN,无需进行反透视,也无需预先知道完整的键集合。任何在任意行中出现的键都会自动包含在结果中。关键要点
Map(LowCardinality(String), String)是 OTel 属性的惯用类型——既足够灵活,能处理不断变化的键集合,又能借助LowCardinality保持键存储的高效性。- 方括号语法 (
map['key']) 是访问值最常见的方式,但要记住它是线性扫描——对于只有几十个键的 Map 完全没问题,但对于几百个键就不太理想了。 - 物化列是解决之道:当某个 map 键变成高频过滤目标时,可将其提升为真正的列,以获得带索引的列式访问。
mapContains、mapKeys、mapValues、mapFilter和ARRAY JOIN为你提供了一套强大的工具,让你无需离开 SQL 就能探索和转换 Map 数据。-Map聚合组合器 (sumMap、avgMap、maxMap等) 会跨行按键分别聚合——非常适合对 OTel 指标计数器进行汇总,而无需预先知道键集合。它还可以与其他组合器配合使用 (例如sumMapIf) 。
