Milvus 3.0 聚合下推:3 层隔离、2 条路径、4 倍安全因子¶
Ch12.086 Milvus 3.0 聚合下推:3 层隔离、2 条路径、4 倍安全因子¶
📊 Level ⭐⭐ | 6.4KB |
entities/milvus-3-0-search-aggregation-pushdown-shuge-2026.md
Milvus 3.0 聚合下推(Search Aggregation & Order By)¶
Milvus 3.0 把分组、聚合、排序从应用层搬进数据库内部,在 ANN 搜索的近似性之上用一层隔离架构补上分析层。核心设计取舍:向量检索本身是近似的,建立在它之上的聚合承认近似,用工程手段在精度和延迟之间权衡。
三层隔离架构:Segcore 只做最笨的事,Proxy 包揽所有聪明的事¶
| 层 | 职责 | 聚合感知 | 嵌套感知 | 排序感知 |
|---|---|---|---|---|
| Segcore | 多字段 flat composite-key group-by | 否 | 否 | 否 |
| QueryNode / Delegator | 合并多 segment 结果,按 composite key 去重 | 否 | 否 | 否 |
| Proxy | 解析 GroupBy 树 → 构建 context → 接收 flat 结果 → 重建层级 + 指标 + 排序 | 是 | 是 | 是 |
Segcore 眼里没有聚合、嵌套、指标,只认「composite key 列表 → 按 key 分组 → 每组返回 top-N」。所有复杂逻辑(层级展开、bucket 指标、排序)压到 Proxy 层。
Top-K 放大公式:segcore_topk = Π(level.size) × group_count_safe_factor,上限 65535。例:10 个 category × 每个 5 个 brand → 10×5×4=200,多拉 4 倍数据降漏桶概率。
设计动机:Segcore 是 C++ 跑在查询引擎热路径上,复杂聚合/嵌套重建会严重影响延迟;重逻辑放 Go 写的 Proxy 层——改聚合逻辑不需要动 Segcore 二进制。
两条路径:Legacy GroupBy vs Search Aggregation¶
| SearchGroupBy(legacy) | SearchAggregation(新) | |
|---|---|---|
| 触发条件 | group_by_field_id > 0 | agg_info != nil |
| 线载体 | SearchResultData.group_by_field_value (field 8) | SearchResultData.fields_data |
| 能力 | 单字段去重 | 多字段 composite key、分组内指标、bucket 排序、嵌套子分组 |
用户文档严重落后于实现:v3.0.x 官方 grouping-search 页面只覆盖基础单字段参数,新聚合 API 只字未提——与功能默认关闭有关。
近似不是 Bug,是设计选择¶
官方口径:Search aggregation 在 ANN 检索结果集上进行而非全量数据,分面计数是近似值;需要精确计数用 query-side aggregation(全量扫描)。
近似三层面: 1. Bucket 存在性不保证——ANN 检索池外的 key 不可见 2. count 只统计检索池中的行——实际 20 个片段只召回 5 个,count 就是 5 3. 嵌套指标偏差随层级传播放大——层级越深偏差越严重
缓解:group_count_safe_factor(默认 4),类似 Elasticsearch 的 shard_size。判断标准:实时推荐场景近似聚合够用;BI 报表要精确计数用 query-side。
Search Order By vs Query Order By¶
Search Order By:完全在 Proxy 层执行(reduce → merge_ids → requery → gen_ids → organize → pick → order_by,internal/proxy/search_pipeline.go:1808)。限制:必须 requery 获取字段值(多一次网络往返);排序无下推。支持多字段(优先级递减)、JSON 子路径(metadata["price"])、sort.SliceStable 保持等值行原始顺序。微妙点:按每组 top entity 的标量值排序组(取每组第一行 price,非平均值)。
Query Order By:下推 Segcore 执行,SortBuffer 组件(internal/core/src/exec/SortBuffer.h)Velox 风格——只排序指针(8 字节)不移动行数据;多字段独立 ASC/DESC 和 NULLS FIRST/LAST;limit < n/2 时 partial_sort 做 O(n log k)。已知限制:无 max_sort_rows 守卫,超大结果集排序有内存风险。
分化原因:Query 全量扫描数据在 Segcore 本地,排序跟着数据走可下推;Search 是 ANN 结果分散多 segment,必须 Proxy 合并后排序。
共享聚合框架 internal/agg/¶
AggregateBase 接口五方法(Update / NewState / UpdateState / Terminate / ToPB),Sum/Count/Min/Max/Avg(拆 sum+count 两 slot)实现,Search 和 Query 两条路径复用同一套指标计算。时间线:20260130 三层架构 → 20260203 Query 排序 → 20260413 Search 聚合完整 MEP。
落地状态与行业位置¶
proxy.search.embeddedAggregation.enabled 在 3.0 GA 默认 off。Phase 1 边界:指标只支持 count/sum/avg/max/min;bucket 排序支持 _count/_key/指标别名;不支持 hybrid search + group_by、highlight、JSON 字段、limit 与 group_by 同用;metric_safe_factor 是 proto 保留字段(no-op)。
Milvus 3.0 不是变成 Elasticsearch:ES 聚合基于全量倒排索引(精确),Milvus 基于 ANN 检索结果集(近似)。Airbyte 测试:纯向量搜索 Milvus 快约 15%、p95 好约 20%;混合负载仍是 ES 强项。行业方向一致:SingleStore 实时聚合+向量、pgvector 混合负载、MariaDB 2026 加向量搜索——向量数据库从「存向量搜向量」挪向分析型数据库。
→ 原文存档
关联¶
- 姊妹篇: Milvus Segment 生命周期(L0/L1/L2 三级分层与删除机制) — 同为术哥源码分析系列,聚合 vs 生命周期
- 同类: 火山 Milvus 向量检索性能 — 检索性能 vs 检索后分析