向量数据库:AI 时代的“记忆中枢”

afcppe 发布于 24 天前 12 次阅读



1. 为什么需要向量数据库?

在传统的 SQL/NoSQL 数据库里,我们存储的是结构化半结构化数据:订单、用户资料、JSON 文档……
但在大模型、推荐、搜索、RAG(Retrieval-Augmented Generation)等场景里,核心数据变成了高维向量(embedding)。
这些向量往往有 128、512、1536 甚至 4096 维,传统数据库无法高效地“按距离”检索,于是向量数据库应运而生。

一句话总结:

向量数据库 = 存储 + 索引 + 距离计算,专为“相似度搜索”优化。


2. 核心概念速览

概念解释举例
Embedding把文本/图片/音频映射成固定维度的向量OpenAI text-embedding-3-small → 1536 维
距离度量如何定义“相似”L2(欧氏)、IP(内积)、Cosine
ANN近似最近邻搜索,牺牲少量精度换性能HNSW、IVF、DiskANN
索引把向量组织成可快速剪枝的结构HNSW 图、IVF 倒排
过滤搜索先按标量过滤,再向量检索where city='Shanghai' and price<100

3. 主流产品全景图(2025)

产品开源/商业语言特点场景
Milvus 2.xApache 2.0Go/C++云原生、分布式、支持 GPU百亿级向量、多租户
WeaviateBSDGoGraphQL API、内置向量化模块知识图谱、RAG
QdrantApache 2.0Rust过滤+向量混合查询、Rust 性能中小规模、边缘部署
Pinecone商业SaaS全托管、自动扩缩容初创公司、快速 PoC
pgvectorPostgreSQL 扩展C与 SQL 无缝融合已有 PG 栈、低学习成本
ChromaApache 2.0Python轻量级、嵌入式Notebook、原型验证

4. 技术内幕:HNSW 索引是如何工作的?

HNSW(Hierarchical Navigable Small World)是当前最热门的 ANN 算法之一,兼顾了召回率延迟

  1. 分层图
    最上层稀疏、最下层稠密,像“高速公路”+“城市道路”。
  2. 贪心搜索
    从上层入口节点开始,每层找局部最优邻居,逐层下降。
  3. 动态插入
    新向量插入时,只更新局部邻居,避免全局重建。

示意图(ASCII):

Layer 2:  A ---------> C
Layer 1:  A <-> B <-> C <-> D
Layer 0:  A-B-C-D-E-F-G-H  (全连接)

5. 实战:用 Milvus 构建“以图搜图”服务

5.1 环境准备

# 1. 启动 Milvus standalone(Docker Compose)
wget https://github.com/milvus-io/milvus/releases/download/v2.4.5/milvus-standalone-docker-compose.yml
docker compose -f milvus-standalone-docker-compose.yml up -d

# 2. 安装 Python SDK
pip install pymilvus==2.4.5 pillow torch torchvision

5.2 生成图片向量

# encode.py
import torch, torchvision.transforms as T
from torchvision.models import resnet50
from PIL import Image
import os, json, numpy as np

device = 'cuda' if torch.cuda.is_available() else 'cpu'
model = resnet50(weights='IMAGENET1K_V2')
model.fc = torch.nn.Identity()  # 去掉分类头
model.eval().to(device)

transform = T.Compose([
    T.Resize(256),
    T.CenterCrop(224),
    T.ToTensor(),
    T.Normalize([0.485,0.456,0.406],
                [0.229,0.224,0.225])
])

def encode_image(path):
    img = Image.open(path).convert('RGB')
    x = transform(img).unsqueeze(0).to(device)
    with torch.no_grad():
        vec = model(x).cpu().numpy().astype('float32')
    return vec.flatten()

# 批量处理
vectors, ids = [], []
for idx, file in enumerate(os.listdir('images')):
    vec = encode_image(f'images/{file}')
    vectors.append(vec)
    ids.append(idx)

np.save('vectors.npy', np.vstack(vectors))
json.dump(ids, open('ids.json','w'))

5.3 建表 & 插入

# milvus_demo.py
from pymilvus import (
    connections, FieldSchema, CollectionSchema,
    DataType, Collection, utility
)

connections.connect(alias="default", host="localhost", port="19530")

# 1. 定义 schema
dim = 2048  # ResNet50 输出维度
fields = [
    FieldSchema(name="id",    dtype=DataType.INT64, is_primary=True),
    FieldSchema(name="vec",   dtype=DataType.FLOAT_VECTOR, dim=dim)
]
schema = CollectionSchema(fields, "Image search demo")
collection = Collection("img_search", schema)

# 2. 创建 HNSW 索引
index_params = {
    "index_type": "HNSW",
    "metric_type": "L2",
    "params": {"M": 16, "efConstruction": 200}
}
collection.create_index("vec", index_params)
collection.load()

# 3. 插入数据
import numpy as np, json
vectors = np.load('vectors.npy')
ids = json.load(open('ids.json'))
entities = [ids, vectors.tolist()]
collection.insert(entities)
collection.flush()

5.4 查询

# search.py
from pymilvus import connections, Collection
import encode  # 复用上面的 encode_image

connections.connect("default", host="localhost", port="19530")
collection = Collection("img_search")
collection.load()

query_vec = encode.encode_image('query/cat.jpg').tolist()
search_params = {"metric_type": "L2", "params": {"ef": 64}}
results = collection.search(
    data=[query_vec],
    anns_field="vec",
    param=search_params,
    limit=5,
    output_fields=["id"]
)

for hits in results:
    for hit in hits:
        print("id:", hit.id, "distance:", hit.distance)

6. 性能调优清单

维度建议
索引类型百万级用 HNSW;十亿级用 IVF_PQ 或 DiskANN
维度高维(>1024) 建议量化(INT8/INT4)
内存HNSW 内存 ≈ 1.1 × 向量数 × 维度 × 4B
并发调整 ef 参数:查询延迟 vs 召回率
过滤先标量过滤再向量搜索,减少候选集

7. 常见坑 & 解决方案

  1. 维度不一致
    报错:dimension not match
    → 插入前统一做 assert vec.shape[0] == dim
  2. 召回率下降
    可能 ef 太小,或量化损失过大。
    → 线上 A/B 测试,逐步调大 ef 或降低量化比例。
  3. 内存爆炸
    单机 HNSW 无法承载十亿向量。
    → 使用 Milvus 分布式模式,或 DiskANN 磁盘索引。

8. 未来展望

  • 多模态融合:一张图 + 一段文本 → 联合向量
  • 实时增量:Kafka → Embedding 模型 → 向量 DB → 毫秒级更新
  • Serverless:按查询计费,无需关心分片、副本
  • 硬件加速:GPU 索引(NVIDIA RAFT)、CXL 内存池

9. 一句话总结

向量数据库不是“又一个 NoSQL”,而是 AI 应用的核心基础设施
从推荐、搜索到 AIGC,谁能把 Embedding 存得快、搜得准,谁就拥有了下一代数据平台的门票。

Happy embedding!

此作者没有提供个人介绍。
最后更新于 2025-10-13