向量索引 · 完全图解

从「为什么需要」到「各家长什么样」—— 向量索引是什么、解决什么问题、MySQL / ES / Milvus 谁支持

ANN 近似最近邻 IVF / HNSW / DiskANN MySQL 9.0 VECTOR ES dense_vector

①什么是向量索引

一句话:向量索引是专门为了「给定一个向量,快速找出与之最相似的若干向量」而设计的数据结构。普通 B+ 树索引擅长「等于 / 范围 / 前缀」这类精确查询,却无法回答「最像它的是谁」这种语义相似查询——向量索引就是为此而生。

在数据世界里,万物都可以被嵌入模型(Embedding)映射成一组浮点数——一个高维向量:

文本

"猫" → [0.12, -0.3, 0.88, ...] 维度常见 384 / 768 / 1536

图片

ResNet / CLIP 把图像编码成向量,相似图向量距离近

音频 / 视频

同样可向量化,用以内容检索、查重、推荐

这些向量的「相似」用距离衡量:欧氏距离(L2)、内积(IP)、余弦相似度(COSINE)。向量索引的目标,就是让「算距离 + 找最近」这步不要每次都和全库逐个比一遍。

非结构化数据 文本/图/音 Embedding 模型 → 高维向量 向量索引 快速 TopK 相似召回 传统 B+ 树索引管「精确查找」,向量索引管「相似查找」—— 这是两件不同的事

②它到底解决什么问题:暴力搜索不行吗

最直接的方法叫暴力(Flat / Brute Force):拿查询向量和库里每一个向量都算一次距离,排序取最小。问题是——太慢。

复杂度:库里有 N 条向量、每条维度 D,一次查询就要做约 N × D 次浮点运算。
举例:N = 1 亿、D = 768 → 单次查询要 768 亿次运算。即使用 SIMD / GPU 加速,也只能勉强扛到百万级,十亿级根本不现实,且延迟随数据量线性增长。

向量索引的核心思想,就是用「少量精度」换「数量级的速度」——把精确最近邻(KNN)放松为近似最近邻(ANN, Approximate Nearest Neighbor):允许漏掉极少数并非真正最近的向量,但换回几倍到几十倍的召回加速、内存与延迟大幅下降。

暴力 Flat 搜索 查询向量 vs 全库 N 条逐个算距离 复杂度 O(N × D) 准确率 100% · 速度慢 · 吞吐低 向量索引 ANN 预建结构:分区 / 构图 / 量化 查询只走局部,跳过大部分 准确率 ~95%+ · 快几十倍 · 撑十亿级 用少量精度,换数量级的速度 1 亿条:秒级~分钟级 1 亿条:毫秒级

所以:小数据(几万条)暴力即可;一旦上到百万、千万、亿级,向量索引是必选项。

③主流向量索引算法(一图一理)

工业界常见的向量索引,大致分四类思路。理解它们的「取舍三角」:召回率 ↔ 速度 ↔ 内存/磁盘占用。

1) 暴力 Flat —— 不算索引的「索引」

不建结构,存原始向量,查询时全量扫描 + 排序。是准确率 100% 的基线,也是很多库做「精确召回」或小规模数据的默认。缺点是随 N 增大线性变慢。

2) IVF 类(倒排 + 聚类)——「先分桶,再精查」

IVF = Inverted File(倒排文件)。先用 K-Means 把所有向量聚成 nlist 个簇(桶),查询时只拿查询向量去最近的若干簇(nprobe 个)里找,其余簇直接跳过。

关键参数:nlist(簇数,越多越细)、nprobe(查几个簇,越大越准越慢)。典型 nprobe=1~32 即可覆盖大部分数据。
查询 q 簇A 簇B 簇C 簇D 仅检索最近的 nprobe 个簇 IVF:先聚类分桶 → 查询只进最近的几个桶精查,其余跳过

IVF 的压缩变体(省内存,精度略降):

IVF_FLAT

簇里存原始向量,精度最高,但占内存(每条 D×4 字节)。

IVF_PQ

簇内再用 PQ 乘积量化把向量压成极短编码,内存可降 8~32 倍,精度略损。

IVF_SQ8

标量量化:每维从 float32 压成 int8,内存约降 4 倍,简单高效。

3) HNSW 类(图索引)——「跳表式的近邻图」

HNSW = Hierarchical Navigable Small World(分层可导航小世界图)。它建一张多层图:上层节点少、边长(像高速公路,快速拉近大范围),下层节点密、边短(做局部精细跳转)。查询时从顶层「俯冲」到底层,沿途只看邻居,极快收敛到最近点。

第3层(稀疏) 第2层 第1层(稠密) 查询路径:顶层快速俯冲 → 底层局部精查
特点:查询极快(毫秒级)、召回率高,但建图慢、内存占用大(要存整张图)。是 Milvus / ES / 多数向量库的默认高性能索引。

4) DiskANN / 量化类 —— 「放磁盘也能快」

DiskANN 用「可导航小世界图 + 乘积量化 + 磁盘存储 + 缓存」的组合,把十亿级向量放到 SSD 上也能毫秒级查询,显存/内存占用远低于 HNSW。适合数据量极大、想省钱的场景。LSH(局部敏感哈希)、Annoy(随机投影树)则是更早期、工程上逐渐被前几种取代的方案。

算法族思路查询速度内存占用召回率典型用途
Flat全量扫描慢中100%小数据 / 精确基线
IVF_*(PQ/SQ)聚类分桶快低~中高内存敏感、大数据
HNSW分层图极快高很高高并发低延迟
DiskANN图+量化+磁盘快极低高十亿级、省成本

④MySQL 有向量索引吗

有,但很新。传统 MySQL(5.x / 8.0 早期)完全不具备向量能力,只能自己把向量存成 BLOB 然后在应用层算——既慢又难索引。

从 MySQL 8.4 LTS 与 MySQL 9.0(2024 年)起,官方引入了原生的 VECTOR 数据类型与向量检索能力(基于 HNSW 索引),可通过 DISTANCE() 函数做相似度排序。
CREATE TABLE docs (
  id BIGINT PRIMARY KEY,
  embedding VECTOR(1536),
  INDEX idx_vec (VECTOR(embedding)) USING HNSW
);

SELECT id, DISTANCE(embedding, VECTOR('[0.1,0.2,...]')) AS d
FROM docs
ORDER BY d ASC
LIMIT 10;
注意:MySQL 的向量能力是「够用级」——适合「我的主库已经是 MySQL,偶尔想顺带做点相似检索」的场景。它远不如专用向量库:索引类型少(主要靠 HNSW)、缺失标量+向量联合过滤的工程优化、没有 GPU 索引、生态(如 RAG 框架对接)弱。生产级向量检索仍建议用 Milvus / pgvector 等。

⑤Elasticsearch 有向量索引吗

有且相当成熟。ES 从 7.x 起支持 dense_vector 字段类型,8.x 起 kNN 检索(基于 HNSW)已稳定可用,把向量检索直接嵌进你本来就有的搜索里。

# 定义带向量的字段
{
  "mappings": {
    "properties": {
      "title": { "type": "text" },
      "vec": {
        "type": "dense_vector",
        "dims": 768,
        "index": true,
        "similarity": "cosine"
      }
    }
  }
}

# kNN 查询(可和 keyword/range 过滤混用)
{
  "knn": {
    "field": "vec",
    "query_vector": [0.1,0.2,...],
    "k": 10,
    "filter": { "term": { "category": "tech" } }
  }
}
ES 的优势:「全文检索 + 向量检索」一把梭,天然支持标量过滤与向量检索混合、分词、聚合;适合「已经用 ES 做搜索,想加语义/图片检索」的团队。
局限:它是搜索/分析引擎,不是为海量向量而生的专用库——十亿级向量、超高并发、GPU 加速、稀疏/二进制向量、丰富索引类型方面,仍不如 Milvus。

⑥Milvus 的向量索引长啥样

Milvus 通过底层的 Knowhere 引擎集成了上面几乎所有算法,并统一了「建索引 → 查询」的接口。它按数据类型自动推荐索引,也允许你显式指定。常用索引一览:

索引类型算法族存储介质特点 / 适用
FLAT暴力内存100% 精确,小数据基线,不做近似
IVF_FLATIVF 聚类内存精确分桶,召回高,内存大
IVF_PQIVF + 乘积量化内存内存省 8~32×,召回略降
IVF_SQ8IVF + 标量量化内存内存省约 4×,性价比高
HNSW分层图内存默认高性能,超低延迟高召回
DISKANN图 + 量化 + 磁盘SSD十亿级、省内存,Milvus 2.4+
GPU_IVF_PQ / GPU_CAGRAGPU 加速显存极致吞吐,Milvus 2.3+,需 GPU 节点
SPARSE_INVERTED_INDEX稀疏反转内存/磁盘稀疏向量(如 BM25 文本),2.4+ 多向量

在 Milvus 里建索引、查询的样子

from pymilvus import MilvusClient, DataType

client = MilvusClient("milvus.db")  # 或连接集群地址

# 1) 建集合,定义向量字段
schema = MilvusClient.create_schema()
schema.add_field("id", DataType.INT64, is_primary=True)
schema.add_field("vec", DataType.FLOAT_VECTOR, dim=768)
schema.add_field("category", DataType.VARCHAR, max_length=64)
client.create_collection("docs", schema=schema)

# 2) 建向量索引(指定 HNSW,给索引参数)
index_params = MilvusClient.prepare_index_params()
index_params.add_index(
    field_name="vec",
    index_type="HNSW",
    metric_type="COSINE",
    params={"M": 8, "efConstruction": 200},
)
client.create_index("docs", index_params)

# 3) 插入数据后,标量 + 向量混合查询
client.search(
    collection_name="docs",
    data=[[0.1, 0.2, ...]],      # 查询向量
    limit=10,
    filter="category == 'tech'",   # 标量过滤,谓词下推
    output_fields=["id", "category"],
)
Milvus 索引的「可玩点」:
  • 自动索引:不指定 index_type 时,Milvus 按数据类型给默认推荐(浮点向量默认 DISKANN 或 HNSW)。
  • 标量 + 向量联合:标量过滤先缩小候选集,再在子集中做向量检索,效率远高于「全量向量检索后过滤」。
  • GPU 索引:CAGRA / GPU_IVF 直接在显存建图,吞吐碾压 CPU 方案,适合超大并发。
  • 索引可随时切换:同一份数据可建多个索引,按需切换,不影响原始向量。

三家一句话对比

系统有向量索引?主要算法定位
Milvus专注IVF/HNSW/DiskANN/GPU/稀疏专用向量数据库,十亿级、低延迟、RAG 首选
Elasticsearch成熟HNSW (dense_vector)搜索引擎顺带做向量,「全文+向量」混合检索
MySQL 9.0新支持HNSW (VECTOR)关系库尝鲜级,简单场景够用,生产力弱于专用库

⑦选型速查:我该用哪种索引 / 哪个系统

📊 数据量小(< 百万)

FLAT 暴力即可,或 HNSW 都行,先别折腾复杂索引。

⚡ 要低延迟高并发

选 HNSW(内存够)→ 不够再上 GPU CAGRA。

💾 内存紧 / 数据超大

选 IVF_PQ / IVF_SQ8,或 DiskANN 放磁盘。

🔎 已经用 ES / MySQL

顺手用它们的向量能力,别为小需求另起一套。

🚀 十亿级 + RAG 底座

直接用 Milvus,索引按场景在 HNSW/DiskANN/GPU 间选。

🔀 既要文本又要向量

ES 混合检索,或 Milvus 2.5+ 的全文+向量融合。

记住这条主线:向量索引 = 用近似换速度。没它,上亿向量做相似检索在时延上根本不可行;有了它,毫秒级召回「最像」的内容才成为日常——这正是语义搜索、推荐、RAG、以图搜图、声纹比对等应用能跑起来的底层原因。