Milvus
Zilliz
  • Home
  • Blog
  • Milvus 中的 JSON 粉碎功能:以 88.9 倍的速度灵活过滤 JSON

Milvus 中的 JSON 粉碎功能:以 88.9 倍的速度灵活过滤 JSON

  • Engineering
December 04, 2025
Jack Zhang

现代人工智能系统正在产生比以往更多的半结构化 JSON 数据。客户和产品信息被压缩成一个 JSON 对象,微服务在每次请求时都会发出 JSON 日志,物联网设备以轻量级 JSON 有效载荷的形式流式传输传感器读数,如今的人工智能应用也越来越多地采用 JSON 作为结构化输出的标准。结果,大量类似 JSON 的数据涌入向量数据库。

传统上,处理 JSON 文档有两种方法:

  • 将 JSON 的每个字段预先定义为固定的 Schema 并建立索引:这种方法可以提供稳定的查询性能,但比较死板。一旦数据格式发生变化,每个新字段或修改字段都会引发新一轮痛苦的数据定义语言(DDL)更新和 Schema 迁移。

  • 将整个 JSON 对象存储为单列(Milvus 中的 JSON 类型和动态 Schema 都使用这种方法):该选项具有出色的灵活性,但代价是查询性能下降。每次请求都需要进行运行时 JSON 解析,通常还需要进行全表扫描,从而导致延迟随着数据集的增长而激增。

这曾经是灵活性和性能的两难选择。

有了Milvus 新推出的 JSON 切碎功能,这种情况就不会再发生了。

随着JSON Shredding 功能的推出,Milvus 实现了无 Schema 灵活性和列式存储的性能,最终使大规模半结构化数据变得既灵活又便于查询。

JSON 破碎处理的工作原理

JSON 切碎通过将基于行的 JSON 文档转换为高度优化的列式存储,加快了 JSON 查询的速度。Milvus 为数据建模保留了 JSON 的灵活性,同时自动优化列式存储--显著提高数据访问和查询性能。

为了有效处理稀疏或罕见的 JSON 字段,Milvus 还为共享键提供了反转索引。所有这些对用户来说都是透明的:你可以像往常一样插入 JSON 文档,让 Milvus 在内部管理最佳存储和索引策略。

当 Milvus 接收到具有不同形状和结构的原始 JSON 记录时,它会分析每个 JSON 关键字的出现率和类型稳定性(其数据类型在不同文档中是否一致)。根据分析结果,每个关键字被分为以下三类:

  • 类型键:出现在大多数文档中且始终具有相同数据类型的键(例如,所有整数或所有字符串)。

  • 动态键:经常出现但具有混合数据类型(如有时是字符串,有时是整数)的键。

  • 共享键:不经常出现、稀疏或嵌套的键,低于可配置的频率阈值。

Milvus 对每个类别都有不同的处理方式,以最大限度地提高效率:

  • 类型键存储在专用的强类型列中。

  • 动态键则根据运行时观察到的实际值类型放置在动态列中。

  • 类型化列和动态列都以 Arrow/Parquet 列格式存储,以实现快速扫描和高度优化的查询执行。

  • 共享键被合并到一个紧凑的二进制-JSON 列中,并附带一个共享键反转索引。该索引通过提前剪切不相关的行,并将搜索范围限制在仅包含所查询键的文档上,从而加快了低频字段的查询速度。

这种自适应列式存储和倒排索引的组合构成了 Milvus JSON 切碎机制的核心,既能实现灵活性,又能实现高性能。

整体工作流程如下图所示:

既然我们已经介绍了 JSON 破碎机制的基本工作原理,下面就让我们来详细了解使这种方法既灵活又高性能的关键功能。

切碎和列化

当编写新的 JSON 文档时,Milvus 会将其分解并重组为优化的列式存储:

  • 类型键和动态键会被自动识别并存储在专用列中。

  • 如果 JSON 包含嵌套对象,Milvus 会自动生成基于路径的列名。例如,user 对象中的name 字段可以用列名/user/name 来存储。

  • 共享键一起存储在一个紧凑的二进制 JSON 列中。由于这些键出现的频率不高,Milvus 会为它们建立一个倒排索引,从而实现快速过滤,让系统能快速找到包含指定键的行。

智能列管理

除了将 JSON 粉碎成列外,Milvus 还通过动态列管理增加了一层智能,确保 JSON 粉碎在数据演变时保持灵活性。

  • 根据需要创建列:当传入的 JSON 文档中出现新的键时,Milvus 会自动将具有相同键的值分组到专用列中。这就保留了列式存储的性能优势,而无需用户预先设计 Schema。Milvus 还能推断新字段的数据类型(如 INTEGER、DOUBLE、VARCHAR),并为其选择高效的列格式。

  • 每个键都会自动处理:Milvus 会分析和处理 JSON 文档中的每个键。这确保了广泛的查询覆盖范围,而不会强迫用户预先定义字段或建立索引。

查询优化

一旦数据被重组到正确的列中,Milvus 就会为每个查询选择最有效的执行路径:

  • 对键入键和动态键进行直接列扫描:如果查询的目标字段已被拆分为自己的列,Milvus 可以直接扫描该列。这就减少了需要处理的数据总量,并利用 SIMD 加速列计算实现更快的执行速度。

  • 共享键的索引查找:如果查询涉及的字段没有提升到自己的列中(通常是稀有键),Milvus 会根据共享键列对查询进行评估。在这一列上建立的反转索引允许 Milvus 快速识别哪些行包含指定的键,并跳过其余行,从而显著提高低频字段的性能。

  • 自动元数据管理:Milvus 可持续维护全局元数据和字典,因此即使传入的 JSON 文档的结构随时间演变,查询也能保持准确和高效。

性能基准

我们设计了一个基准来比较将整个 JSON 文档存储为单个原始字段与使用新发布的 JSON 切碎功能的查询性能。

测试环境和方法

  • 硬件:1 核/8GB 集群

  • 数据集来自JSONBench的 100 万个文档

  • 测试方法测量不同查询模式下的 QPS 和延迟

结果:键入键

该测试测量的是查询大多数文档中存在的键时的性能。

查询表达式QPS (不粉碎)QPS (有粉碎)性能提升
json['time_us'] > 08.69287.533x
json['kind'] == 'commit8.42126.114.9x

结果:共享键

本次测试的重点是查询属于 "共享 "类别的稀疏嵌套键。

查询表达式QPS (不粉碎)QPS (已粉碎)性能提升
json['identity']['seq'] > 04.3338588.9x
json['identity']['did'] == 'xxxxx'7.635246.3x

共享密钥查询显示了最显著的改进(快达 89 倍),而键入密钥查询则持续提高了 15-30 倍。总体而言,每种查询类型都能从 JSON Shredding 中获益,性能提升非常明显。

立即试用

无论您是在处理 API 日志、物联网传感器数据,还是在处理快速发展的应用有效载荷,JSON Shredding 都能为您提供罕见的灵活性和高性能。

该功能现已推出,欢迎立即试用。您还可以查看此文档了解更多详情。

对最新版 Milvus 的任何功能有疑问或想深入了解?加入我们的 Discord 频道或在 GitHub 上提交问题。您还可以通过 Milvus Office Hours 预约 20 分钟的一对一课程,获得见解、指导和问题解答。

    Try Managed Milvus for Free

    Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

    Get Started

    Like the article? Spread the word

    扩展阅读