Agent 动态 JSON 性能拆解:Apache Doris 比 CK 快 7 倍、比 ES 快 2 倍

举报
SelectDB技术团队 发表于 2026/07/10 14:55:51 2026/07/10
【摘要】 AI Agent 的日志正在变得越来越复杂。过去日志通常只有时间、级别和消息,但现在一次 Agent 调用可能包含模型参数、工具调用、检索结果、Prompt 版本、用户上下文等大量动态字段。这些字段很难提前设计 schema,于是 JSON 成为了最自然的数据承载方式。问题也随之出现:当 payload (即结构经常变化、字段无法提前固定的 JSON 数据)从几十个字段扩展到几百、几千个字段...

AI Agent 的日志正在变得越来越复杂。过去日志通常只有时间、级别和消息,但现在一次 Agent 调用可能包含模型参数、工具调用、检索结果、Prompt 版本、用户上下文等大量动态字段。这些字段很难提前设计 schema,于是 JSON 成为了最自然的数据承载方式

问题也随之出现:当 payload (即结构经常变化、字段无法提前固定的 JSON 数据)从几十个字段扩展到几百、几千个字段时,数据库还能不能像查询普通列一样,高效分析这些动态 JSON?

上一篇我们讨论了 AgentLogsBench 的设计目标和综合测试结果。Benchmark 只是现象,更值得追问的是:

为什么同样都支持 JSON,不同数据库在 Agent 日志场景下的性能差异会如此明显

这一篇,我们把视角进一步下沉,聚焦 AgentLogsBench 中与动态 JSON / Variant 最相关的一组查询,看看当 payload 持续变宽、字段不断演进时,系统到底应该如何存储和执行 JSON Path 查询。

Agent 日志为什么会放大 JSON 性能差异

关于 AgentLogsBench 的整体数据集、查询模型和测试方法,上一篇已经做过介绍,这里不再重复展开。本文只聚焦其中一个关键点:Agent 日志中的动态 payload。

在一条 agent trace 中,稳定字段适合提升为列,用于检索、过滤和聚合;而变化更快、来源更复杂的字段,则会不断进入 payload。例如模型返回状态、工具执行结果、OpenTelemetry 状态码、Prompt template、workflow variant、request key 等。

一行 observation 大致会长这样:

{
  "event_time": "2026-04-01T12:00:00Z",
  "trace_id": "trace_000001",
  ...
  "payload": {
    "provider": {
      "stop_reason": "tool_use",
      "cache_hit": false
    },
    "tool_result": {
      "stderr": "unable to open ...",
      "exit_code": 1
    },
    "otel": {
      "status_code": "ERROR"
    }
  }
}

JSON分析的难点在于:

当 schema 持续变化时,系统还能不能像访问结构化列一样,对这些动态字段做低延迟过滤、聚合、全文检索和成本分析

与上一篇介绍的数据模型一致,AgentLogsBench 始终要求所有系统在同一张 agent_observations 表上完成查询,不允许通过预先 flatten JSON、拆分辅助表或预定义所有字段来规避动态 schema 的挑战。

因此,测试的关键在于:

谁能在动态字段持续增长的情况下,同时完成检索、过滤、聚合和分析

这正好贴近 Agent observability(Agent 可观测性) 的真实问题。字段会随着模型、工具、框架、客户配置和 workflow 演进而不断变化,但排障和分析仍然要求低延迟响应。

先看测试结果

查询延迟:Doris 的优势主要在动态字段分析

上一篇已经介绍了综合排行榜。这里只拆开与 Variant / JSON Path 最相关的一组查询。

为了便于阅读,主表只保留关键对照:Apache Doris、ClickHouse、Elasticsearch、OpenSearch。完整公开结果仍包含 DuckDB 和 PostgreSQL。

根据表格的结论如下:

  • Elasticsearch / OpenSearch 在全文检索相关查询上依然很强,Q19 甚至可以打平 Doris。
  • ClickHouse 存储压缩很好,但在动态 payload 查询上延迟明显更高。
  • Doris 的优势主要体现在 Q10、Q12、Q16、Q20 这类动态字段聚合、rollup 和低基数过滤上。
  • 在本文关注的 JSON Path 分析查询集合中(Q07、Q10、Q12、Q16、Q17、Q18、Q20),ClickHouse 的平均延迟约为 Doris 的 7.4 倍,Elasticsearch / OpenSearch 约为 Doris 的 2.4 倍。

这说明,在 Agent observability 里,搜索只是第一步。找到异常记录之后,开发者通常还要继续按 payload 字段过滤、统计错误分布、比较不同 prompt、模型版本、发布环和客户等级。

因此,决定整体体验的不是单次搜索速度,而是搜索之后还能否低成本完成动态字段查询、聚合和关联分析。Doris 的优势也主要体现在这里。

存储空间:Doris 搜索能力与存储成本间的平衡

存储结果也反映了不同系统的取舍。

  • ClickHouse 最省空间,符合它在列式压缩上的一贯优势。
  • Elasticsearch / OpenSearch 存储占用明显更高,因为它们需要为倒排索引、词项字典、短语查询等维护额外结构。
  • Doris 的取舍更接近混合负载系统:它同时支持全文检索和动态 payload 查询,但 100M 数据规模下的存储占用只有 Elasticsearch / OpenSearch 的约三分之一,同时接近 ClickHouse 的量级。

这也是 Doris 综合表现较好的原因之一:是在列式分析系统内部同时提供 Variant、倒排索引、SQL 聚合和缓存能力

Doris Variant:把动态 JSON 纳入列式执行链路

从 JSON Path 到列式 subcolumns

Doris VARIANT 的关键不是支持 JSON 语法,而是把常用 JSON Path 变成内部列式 subcolumns。

写入时,Doris 会对 JSON Path 做解析、类型推断和 subcolumnization。查询时,用户仍然写 JSON Path:

SELECT
    CAST(payload['attr']['release_ring'] AS STRING) AS release_ring,
    CAST(payload['attr']['customer_tier'] AS STRING) AS customer_tier,
    count(*) AS observations,
    avg(latency_ms) AS avg_latency_ms,
    sum(total_cost) AS total_cost
FROM agent_observations
WHERE type IN ('GENERATION', 'TOOL', 'RETRIEVAL')
GROUP BY
    CAST(payload['attr']['release_ring'] AS STRING),
    CAST(payload['attr']['customer_tier'] AS STRING)
ORDER BY observations DESC
LIMIT 50;

但执行器会优先命中内部列式存储。

这也是 Q12 这类查询快的原因:它表面上是在读 payload,实际是在读若干 typed subcolumns,并且可以做列裁剪、向量化执行、局部字典 / 压缩和索引过滤。

可以简单理解为:传统 JSON 查询像是在一个大文件里不断翻找字段,而 Variant 会把经常访问的 JSON 路径拆出来,让它们拥有类似普通数据列一样的查询能力。

宽 JSON 的真正瓶颈:热点路径和长尾字段混在一起

Agent logs 的 payload 会越来越宽。有些路径会变成热点,例如:

  • payload.attr.release_ring
  • payload.attr.customer_tier
  • payload.provider.cache_hit
  • payload.provider.stop_reason

但更多字段会非常长尾,来自不同模型、工具、插件、客户配置和 workflow。

如果系统把所有路径一视同仁,就会出现一个问题:明明只查几个热点字段,却被大量 metadata、稀疏列和长尾字段拖慢。

Doris 的处理方式是:高频路径列式化,低频路径进入 sparse columns 或 DOC encoding,并且在宽列场景推荐 Storage Format V3。

当 VARIANT 生成大量动态 subcolumns 时,Storage Format V3 可以将列元数据从 Segment Footer 中解耦出来,从而加快文件打开,降低内存开销,使得热点字段像普通列一样低延迟。

其他系统的取舍

DuckDB / Parquet Variant:开放格式强,在线分析链路不足

Parquet Variant / DuckDB Variant 的价值在于开放格式。它们把半结构化数据从 JSON string 推向 typed binary representation,并支持把高频字段 shred 成强类型列。

这很适合湖仓交换、本地分析和跨引擎读写。

但在 AgentLogsBench 的 100M 主测试中,DuckDB 在 JSON Path 查询上没有接近 Doris(DuckDB 在核心查询中的延迟大约在 282.798s 到 7414.692s 之间,而 Doris 为 0.032s 到 1.497s。)。原因在于,开放文件格式主要解决“怎么存得更通用”,Doris Variant 解决的是:在线分析系统如何把动态 JSON 纳入列式存储、索引、compaction 和向量化执行链路。

Elasticsearch / OpenSearch:搜索强,但动态聚合成本高

Elasticsearch / OpenSearch 的强项是搜索。Q17 这类高基数 filter、Q19 这类 text token + rollup 查询,它们表现都很好。

但 dynamic mapping 对字段爆炸敏感。Agent logs 的 payload.attr.*payload.tool_result.*payload.otel.*、框架私有字段和插件字段天然长尾。如果全部映射成可聚合字段,mapping、doc values、heap 和 segment metadata 成本都会上升。

因此,搜索能力仍然很强,但搜索之后的多维聚合、动态字段分析和低成本长期存储,会变得更复杂。

ClickHouse JSON :压缩优势明显,但长尾路径查询仍有代价

ClickHouse 的 JSON 类型已经有 subcolumns 能力,也在持续优化 shared data。但当动态路径超过限制后,长尾路径会进入 shared data。查询这些路径时,往往需要额外读取和过滤。

ClickHouse v25.8 引入了 bucketed / advanced shared data serialization,让系统可以更精细地跳到特定 path 的数据,避免读取过多无关 substreams。但这类设计也有代价:读取完整 JSON 或 merge 可能变慢,因此需要保存额外原始格式副本来平衡兼容性和效率,这也会带来存储开销。

在 100M 公开结果中,ClickHouse 的存储确实更低,但 Q10、Q12、Q16、Q17、Q20 等动态 payload 查询明显慢于 Doris;Q19 更是 30.816s vs Doris 1.013s。

一张表总结:不同系统如何理解 JSON

Doris 把动态 JSON 收进了数据库自己的列式、索引和文件格式体系;其他系统更多是在搜索索引、开放文件格式或行存 JSON 文档的边界内优化。

结束语

总结来看,AgentLogsBench 反映的并不是单个 JSON 函数的性能差异,而是不同系统对动态 JSON 的处理方式差异。

在 Agent 可观测性场景中,payload 会持续变宽,字段会不断演进,但查询热点往往集中在少数业务路径上。系统能否把这些动态路径纳入列式存储、索引、压缩和向量化执行链路,决定了搜索之后的分析体验。

Doris 的优势也正来自这里:它通过 Variant 将动态字段转化为可裁剪、可索引、可聚合的列式结构。对于 AI Agent 日志、事件分析和 RAG / Agent Trace 分析这类负载,这种能力会越来越关键。

如果你想要以全托管的方式运行 Apache Doris,可以选择 SelectDB,它提供了驱动 benchmark 结果的同一套 VARIANT、倒排索引和缓存能力。在这一能力之上,如果进一步将其封装为面向 Agent 的可观测与评估平台—— Litefuse,可以在底层数据能力之上,直接构建 trace 管理、评估体系、查询分析与多租户可观测的一体化平台。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。