在 AI Agent 场景下,万级 JSON 字段导致的元数据膨胀问题,会通过以下路径严重影响 Apache Doris 的写入与查询性能:

1. 对写入性能的影响

  • 写入路径阻塞与吞吐下降:在传统处理方式(如即时物化)下,每个新出现的 JSON key 都会在写入时被尝试物化为独立的子列。当 key 数量达到万级时,写入过程需要处理海量的列创建、类型推断和编码操作,这会导致单次写入的 I/O 和 CPU 开销急剧增加,严重拖慢写入速度,形成写入瓶颈 。
  • Compaction 压力与写放大:频繁的写入会产生大量数据碎片(Segment)。后台的 Compaction 进程在合并这些碎片时,如果面对的是数万列的元数据,其合并、排序和重写的成本会变得极高。这会导致 Compaction 任务积压,不仅占用大量系统资源(CPU、I/O),还可能因来不及合并而影响新数据的导入,甚至引发写入失败 。

2. 对查询性能的影响

  • 元数据加载开销巨大:在 Doris 4.1 之前的 Segment V2 存储格式中,所有列的元数据(如列名、类型、统计信息、索引位置等)都集中存储在文件尾部(Footer)。查询时,即使只访问其中几个字段,也需要先加载整个文件的完整元数据(可能包含上万列的信息)。这带来了巨大的、不必要的 I/O 和内存解析开销,显著延长了查询的初始响应时间(冷启动延迟)。
  • 内存占用激增:将万级字段的元数据全部加载到内存中,会消耗大量的内存资源。在高并发查询场景下,多个查询同时打开不同的数据文件,会导致内存中充斥着大量本次查询并不需要的列元数据,造成内存资源的严重浪费,甚至可能因内存不足而影响查询稳定性或触发 OOM 。
  • 随机读放大:对于未物化或未建立高效索引的字段,查询可能需要回退到扫描原始的文档存储(如 Sharded Map)。虽然 Doris 的 Doc Mode 通过哈希分片减少了扫描范围,但相比直接读取物化后的纯列式数据,其 I/O 效率仍然较低。在极端情况下,对冷字段的查询延迟可能比热点字段高出数十倍 。

3. Apache Doris 4.1 的针对性优化方案

为了应对上述挑战,Apache Doris 4.1 引入了 Doc Mode(延迟物化)Segment V3(按需加载元数据) 两项核心优化。

优化方案对比

性能瓶颈 传统方案的问题 Doris 4.1 优化方案 优化原理与效果
写入与Compaction压力 写入时立即物化所有JSON path为子列,导致写入慢、Compaction任务重。 Doc Mode(延迟物化) 写入时仅将JSON编码为分片的文档结构(Sharded Map)落盘,优先保障写入吞吐。仅在后台Compaction时,根据访问频率将高频path物化为子列,显著降低写入放大和Compaction压力 。
元数据加载开销 查询需加载包含万列信息的完整Footer,I/O与内存开销大。 Segment V3(按需加载) 将列级元数据从集中式的Footer中拆解出来,独立存储。查询时仅加载与查询相关的列的元数据,极大减少了冷启动时的I/O和内存消耗。在万列场景下,文件打开速度提升可达16倍,内存占用降低可达60倍
冷字段查询效率 未物化字段查询需全量扫描原始JSON,效率低下。 Doc Mode的三档读路径 系统根据字段物化状态自动选择最优路径:1. 列式路径(对已物化字段);2. 分片扫描(对未物化字段,仅扫描对应哈希分片);3. 全文档读取(用于SELECT *)。实现了性能与灵活性的平衡 。

4. 实际效果与代码示例

根据基准测试(万级JSON path,1亿行数据),优化后的Doris在宽JSON场景下表现均衡:

  • 写入性能:Variant Doc Mode的写入吞吐优于ClickHouse和Elasticsearch,接近PostgreSQL JSONB的水平 。
  • 查询性能:在聚合与过滤场景下,Doris查询延迟稳定在百毫秒级,而受元数据与随机读影响的ClickHouse延迟在数秒级;相比行存的PostgreSQL JSONB,Doris有数量级的性能优势 。
  • 存储效率:得益于纯列式存储和无需冗余副本,Doris的存储空间约为ClickHouse的60% 。

以下是一个启用Doc Mode和Segment V3的建表示例:

-- 建表语句示例,启用Doc Mode和Segment V3存储格式
CREATE TABLE IF NOT EXISTS ai_agent_trace (
    trace_id VARCHAR(64) NOT NULL,
    timestamp DATETIME NOT NULL,
    agent_id VARCHAR(128),
    -- 使用VARIANT类型并启用Doc Mode存储AI Agent复杂的交互数据
    event_data VARIANT<               -- :使用VARIANT类型处理半结构化JSON
        'prompt' : STRING,
        'tool_call' : ARRAY<STRING>,
        'response' : STRING,
        properties(
            'variant_enable_doc_mode' = 'true'  -- :关键配置,启用Doc Mode延迟物化
        )
    >,
    -- 可以为高频查询的字段创建倒排索引加速过滤
    INDEX idx_event_data(event_data) USING INVERTED PROPERTIES("field_pattern" = "status")
)
DUPLICATE KEY(`trace_id`, `timestamp`)
DISTRIBUTED BY HASH(`agent_id`) BUCKETS 16
PROPERTIES (
    "replication_num" = "1",
    "storage_format" = "V3"  -- :启用Segment V3格式,实现元数据按需加载
);

查询时,可以像访问普通列一样访问JSON中的字段,优化器会自动选择最佳路径:

-- 查询示例:分析特定工具调用频率
SELECT
    DATE(timestamp) as day,
    -- 直接通过JSON路径访问已物化或未物化的字段,系统自动路由
    event_data['tool_name'] as tool,
    COUNT(*) as call_count
FROM ai_agent_trace
WHERE -- 条件过滤,可能利用Doc Mode的分片扫描或列式索引
    event_data['tool_name'] IS NOT NULL 
    AND event_data['status'] = 'success'
GROUP BY day, tool
ORDER BY day DESC, call_count DESC
LIMIT 100;

综上所述,通过 Doc Mode 将写入时的即时列化压力后置到Compaction阶段,并结合 Segment V3 彻底改革元数据的加载方式,Apache Doris 4.1 有效地打破了万级JSON字段带来的元数据膨胀与性能恶化循环,在AI Agent这类高稀疏、高演化、混合读写负载的场景下,实现了写入吞吐、查询延迟与资源开销之间的良好平衡。


参考来源

Logo

更多推荐