向量数据库--Milvus--2--介绍

七、混合检索(Hybrid Search)

原理

同时执行多种检索方式(向量语义检索 + BM25 全文检索),各取 TopK,然后融合排序,最终返回 TopN。

代码示例

python 复制代码
from pymilvus import WeightedRanker, RRFRanker

results = client.hybrid_search(
    collection_name="articles",
    reqs=[
        {"data": [query_vector], "anns_field": "vector", "limit": 10},  # 向量检索
        {"data": [query_text],  "anns_field": "sparse",  "limit": 10},  # BM25全文检索
    ],
    rerank=WeightedRanker(0.7, 0.3),  # 加权融合:向量70%,BM25 30%
    limit=5,                          # 最终返回5条
)

为什么需要混合检索

复制代码
纯向量检索:抓"语义相近",但可能漏掉关键词精确匹配
纯BM25检索:抓"关键词命中",但理解不了语义
混合检索:两者结合,既不漏语义也不漏关键词

融合策略

策略 原理 特点
WeightedRanker 按分数加权 需要调权重,调优后效果更好
RRFRanker 按排名倒数融合 不需要调参,通用场景首选

前提条件

建表时需定义稠密向量和稀疏向量两个字段:

python 复制代码
client.create_collection(
    collection_name="articles",
    fields=[
        {"name": "id", "type": "INT64", "is_primary": True},
        {"name": "vector", "type": "FLOAT_VECTOR", "dim": 384},    # 稠密向量
        {"name": "sparse", "type": "SPARSE_FLOAT_VECTOR"},          # 稀疏向量(BM25)
        {"name": "text", "type": "VARCHAR", "max_length": 1000},
    ]
)

八、面试常见问题

基础概念

问题 简答
Milvus 是什么? 向量数据库,存储高维向量,做 ANN 相似度检索
为什么不用 MySQL 存向量? MySQL 没有 ANN 索引,百万级数据全表计算就卡死
支持哪些相似度计算? L2(欧氏距离)、IP(内积)、COSINE(余弦相似度)
检索结果是精确的吗? 不是,ANN 是近似算法,召回率通常 95%+

索引与性能

问题 简答
有哪些索引类型? FLAT、IVF、HNSW、DISKANN
HNSW 为什么快? 多层跳表,O(logN) 复杂度
IVF 的 nlist/nprobe? nlist 分桶数,nprobe 搜索桶数,nprobe 越大召回越高但越慢
查询慢怎么优化? 检查索引是否生效、调 nprobe/ef 参数、数据量是否超内存

架构与原理

问题 简答
整体架构? 存算分离,Coordinator 调度 + Worker 计算 + 对象存储持久化 + etcd 元数据
写入流程? 写消息日志 → 消费写入对象存储 → Growing Segment(可查)→ Seal 后建索引
插入后多久能查到? 近实时,写入后进入 Growing Segment 立即可查,但无索引是暴力扫描

实战场景

问题 简答
向量维度怎么选? 取决于 Embedding 模型,BERT 768维,OpenAI 1536维
百亿级怎么处理? 分 Collection/Partition + DISKANN + 分布式集群
Embedding 模型升级维度变了? 新建 Collection,重新生成全量向量,迁移数据
能替代 MySQL 吗? 不能,无 JOIN/聚合,通常 Milvus + MySQL 配合

九、选型建议

场景 推荐
本地开发/测试 Milvus Lite(pip install,无需 Docker)
生产单机 Docker 单机版
生产集群 Milvus 分布式 + etcd + MinIO
云托管 Zilliz Cloud(Milvus 官方云服务)

与其他向量数据库对比

数据库 类型 特点
Milvus 开源 国产、生态全、十亿级
Pinecone 云托管 闭源SaaS、开箱即用
pgvector PG 插件 SQL 原生、迁移成本低
Qdrant 开源 Rust、性能好
Weaviate 开源 内置向量化模块
Chroma 开源 轻量级、适合原型
FAISS Meta 开源、纯计算库、极致性能

十、Milvus vs MySQL

Milvus 和 MySQL 是互补关系,不是替代关系。核心区别在于设计目标不同:MySQL 解决结构化数据的精确查询和事务,Milvus 解决高维向量的近似最近邻检索。

事务与一致性

MySQL Milvus
事务 ACID,BEGIN/COMMIT/ROLLBACK 无事务,每条插入独立
两阶段提交 支持(XA 协议) 不支持
回滚 支持 不支持
隔离级别 4 种(RU/RC/RR/Serializable) 无隔离级别概念
一致性 强一致 最终一致(写入后近实时可查)

并发与锁

MySQL Milvus
行锁 共享锁/排他锁 无锁
表锁 支持
写写并发 行锁串行化 消息队列串行化(天然有序)
读写并发 MVCC + 锁 读写分离,互不阻塞
死锁 可能发生 不可能

Milvus 不需要锁的原因:追加写入 + segment 不可变。写入追加到消息队列,天然有序;读取操作的是已 Seal 的不可变 segment,和写入互不冲突。不存在"同一个位置两个人同时改"的情况。

数据更新

MySQL Milvus
按主键更新 UPDATE t SET x=1 WHERE id=1 upsert(id=1, ...) 删除旧+插入新
按条件批量更新 UPDATE t SET x=1 WHERE ... ❌ 不支持
部分字段更新 UPDATE t SET category='new' ❌ 必须提供完整数据(含向量)
自增/计算 UPDATE t SET count=count+1 ❌ 不支持

Milvus 的 upsert 本质是删除旧记录 + 插入新记录,不是原地修改。频繁 upsert 会产生碎片,影响查询性能。

查询能力

MySQL Milvus
精确匹配 WHERE id=1 ✅ 标量过滤
向量相似度搜索 ✅ ANN 检索
JOIN
GROUP BY / 聚合
子查询
全文检索 需插件 ✅ 内置 BM25

数据持久化与索引加载

MySQL Milvus
数据存储 磁盘(B+树) 对象存储(S3/MinIO)
写入持久性 WAL + redo log 消息队列 + 对象存储
索引位置 磁盘(按需读页到内存) HNSW/IVF 全在内存,DISKANN 在磁盘
重启恢复 从 WAL/redo log 恢复 从对象存储重新加载索引到内存

生产架构建议

实际生产中通常 MySQL + Milvus 配合使用:

复制代码
用户请求
  ├── MySQL:业务数据、事务、JOIN、聚合
  │   ├── 用户表、订单表
  │   └── 按 id 查业务详情
  │
  └── Milvus:向量检索
      ├── 文章/商品向量
      └── 相似度搜索 → 拿到 id 列表 → 回 MySQL 查详情

典型流程:

复制代码
1. Milvus 向量检索 → 得到 TopK 的 id 列表
2. MySQL SELECT * FROM articles WHERE id IN (...) → 查业务字段
3. 合并返回给前端

十一、Segment 机制

Segment 是 Milvus 数据管理的最小单元,类似 MySQL 的"页"但粒度更大。

复制代码
Collection(表)
  ├── Segment 1(已 Seal,建了 HNSW 索引)→ 内存中可查
  ├── Segment 2(已 Seal,建了 HNSW 索引)→ 内存中可查
  └── Segment 3(Growing,还在写入)→ 内存中可查(暴力扫描)

Segment 生命周期

复制代码
插入数据 → 进入 Growing Segment(可变,追加写入)
    │
    │  写满阈值(默认约 512MB)
    ↓
Seal(冻结,不可变)→ 后台建索引(HNSW/IVF)
    │
    ↓
加载到内存 → 可用索引快速查询

两种 Segment

Growing(成长中) Sealed(已封存)
状态 可变,可追加写入 不可变,冻结
索引 无,暴力扫描 有(HNSW/IVF 等)
查询 能查,但慢(遍历) 能查,快(走索引)
在哪 内存 索引在内存,数据在磁盘

为什么要分 Segment

复制代码
1. 增量建索引
   新写入 10 万条 → 只给这个新 Segment 建索引
   不用重建整个 Collection 的索引

2. 并行查询
   查询时并行扫描所有 Segment → 合并结果
   Segment 1 找到 [A, B, C]
   Segment 2 找到 [D, E, F]
   合并排序 → 返回 TopK

3. 内存管理
   可以单独 load/unload 某些 Segment
   而不是全量加载或全量卸载

和 MySQL 对比

MySQL Milvus
数据单元 页(16KB) Segment(~512MB)
写入方式 原地修改(B+树) 追加到 Growing Segment
冻结机制 Seal 后不可变
建索引 全表建 按 Segment 增量建
相关推荐
像风一样自由202015 小时前
15.Milvus是什么?为什么RAG系统经常使用它?
postgresql·大模型·milvus·rag·智能体
redfred15 小时前
DBeaver 使用教程:开源免费数据库管理工具 100+ 数据库连接 SQL编辑器 ER图 AI生成SQL 全平台
数据库·sql·开源
zcmodeltech15 小时前
垃圾发电厂沙盘模型控制系统设计与实现:多设备协同联动方案
java·大数据·数据库·人工智能·stm32·嵌入式硬件·制造
有续技术15 小时前
工业网关接入 PLC,为什么要先整理点表?
运维·网络·数据库
山峰哥15 小时前
数据库工程:Explain执行计划对比调优实战‌
大数据·数据库·sql·编辑器·深度优先
夜雪一千15 小时前
MySQL Insert Intention Lock 插入意向锁是什么
数据库·mysql
Nontee1 天前
MySQL 插入冲突了怎么办?两种处理方式入门笔记
数据库·笔记·mysql
ltl1 天前
Parquet 文件格式:row group、编码与谓词下推索引
数据库