向量数据库--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 增量建
相关推荐
北风toto8 分钟前
数据库笔记:Armstrong 公理系统与集合论的深度辨析
数据库·笔记
小蒜学长17 分钟前
基于SpringBoot+Vue的租房管理系统的设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端·租房管理
一只专注api接口开发的技术猿18 分钟前
Open‑Claw 实战|告别页面逆向,快速搭建电商商品监控与数据分析完整方案
大数据·数据库·python·数据挖掘·数据分析
雨落在了我的手上19 分钟前
MySQL数据库基础(6):增删改查操作(1)
数据库·mysql
Omics Pro29 分钟前
全新可重分析!代谢组质谱专用
数据库·人工智能·算法·机器学习·自然语言处理
ITOM运维行者40 分钟前
网络丢包监控怎么做?从六大成因到接口级定位的排查路径
数据库·人工智能·机器学习
ao-weilai43 分钟前
MySQL数据库:用户管理
数据库·mysql·adb
冰暮流星1 小时前
sql之is not null运算符
数据库·sql·oracle
冰暮流星1 小时前
sql之is null 运算符
java·数据库·sql