2.2 向量数据库

目录

第一部分:向量数据库核心概念

[1. 什么是向量数据库?](#1. 什么是向量数据库?)

[2. 为什么需要专门的向量数据库?](#2. 为什么需要专门的向量数据库?)

第二部分:核心工具详解

[1. Faiss (Facebook AI Similarity Search)](#1. Faiss (Facebook AI Similarity Search))

[2. Milvus](#2. Milvus)

[3. Elasticsearch (v7.x+)](#3. Elasticsearch (v7.x+))

[第三部分:理解索引结构 - HNSW](#第三部分:理解索引结构 - HNSW)

[1. 核心思想:分层可导航小世界](#1. 核心思想:分层可导航小世界)

[2. 构建过程(插入)](#2. 构建过程(插入))

[3. 搜索过程(查询)](#3. 搜索过程(查询))

[4. 关键参数](#4. 关键参数)

第四部分:对比与总结


第一部分:向量数据库核心概念

1. 什么是向量数据库?

向量数据库是专门用于存储、索引和检索高维向量 的数据库。与传统数据库基于精确匹配(如=)或文本搜索(如LIKE)不同,向量数据库的核心是基于相似性搜索

  • 向量: 将非结构化数据(如图片、文本、音频、视频)通过深度学习模型(如BERT, ResNet, CLIP)转化为的数值数组。例如,一个句子可能被表示为768维的向量。
  • 相似性: 通过计算向量之间的距离(如欧氏距离、余弦相似度)来衡量其相关性。距离越小,相似度越高。
  • 核心能力从海量高维向量中,快速找到与目标向量最相似的K个向量
2. 为什么需要专门的向量数据库?

随着大模型和AI应用(如RAG、推荐系统、图像搜索)的爆发,传统数据库在处理向量相似性搜索时面临挑战:

  • 性能瓶颈: 在海量数据(百万、亿级)中进行"最近邻"搜索是计算密集型操作,传统索引(如B树)效率极低。
  • 精度与速度的权衡 : 精确的K近邻(K-NN)搜索复杂度极高,需要近似最近邻(ANN)搜索在可接受的精度损失下,将搜索速度提升数个数量级。
  • 数据管理: 需要管理向量及其关联的原始数据(元数据),并提供增删改查、持久化、高可用等数据库特性。

第二部分:核心工具详解

这三个工具代表了向量处理领域的三种不同范式。

1. Faiss (Facebook AI Similarity Search)

定位一个专注于向量相似性搜索的库,而非完整数据库。

  • 核心特性
    • 纯C++/Python库: 直接集成到应用中,无服务器进程。
    • 算法丰富: 提供多种索引类型(Flat, IVF, HNSW, PQ等)和精确/近似搜索算法。
    • 极致性能: 高度优化,支持GPU加速,是学术研究和工业界的性能基准。
    • 无数据管理: 不提供持久化(需自己保存索引文件)、无元数据管理、无分布式支持(有基础集群方案)。
  • 部署与使用
    • 部署pip install faiss-cpufaiss-gpu。本质上是导入一个Python库。
    • 典型使用流程
python 复制代码
import faiss
import numpy as np

# 1. 生成数据
d = 128  # 向量维度
nb = 100000  # 数据库大小
x = np.random.random((nb, d)).astype('float32')

# 2. 构建索引(以HNSW为例)
index = faiss.IndexHNSWFlat(d, 32)  # 32为构建参数
index.add(x)

# 3. 搜索
k = 10  # 返回最近邻数量
query = np.random.random((1, d)).astype('float32')
distances, indices = index.search(query, k)
print(indices, distances)
# [[31680 40123 93393 67177 59492 78627 3882 43555 93068 19121]] [[13.229351 14.017465 14.350857 14.728469 14.749828 14.847415 14.975938 14.987753 15.016882 15.203573]]
  • 适用场景: 研究原型、需要极致性能的嵌入式系统、作为其他系统(如Milvus)的底层引擎。
2. Milvus

定位云原生、功能完备的开源向量数据库。

  • 核心特性
    • 数据管理: 支持完整的CRUD操作、数据持久化、快照、数据压缩。
    • 元数据管理 : 通过集合(Collection)和分区(Partition)组织数据,支持标量字段过滤(如where price < 100)。
    • 高性能ANN: 集成多种索引(Faiss, HNSW, ANNOY等),自动执行查询优化。
    • 分布式与高可用: 采用存算分离架构(对象存储 + 消息队列 + 协调服务),易于水平扩展。
    • 丰富的SDK和工具: 支持多种语言,提供图形化管理工具(Attu)。
  • 部署与使用
    • 部署
      1. 单机版(开发): 使用Docker Compose快速启动所有组件。
      2. 集群版(生产): 使用Kubernetes Helm Chart或云服务(Zilliz Cloud)。
    • 典型使用流程(PyMilvus SDK)
python 复制代码
# 安装 Milvus Lite
# pip install milvus pymilvus
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType, utility
from milvus import default_server
import numpy as np

# 启动内置服务器
default_server.start()

# 连接
connections.connect(host='127.0.0.1', port=default_server.listen_port)

# 检查集合是否存在,如果存在则删除
collection_name = "my_news"
if utility.has_collection(collection_name):
    print(f"集合 '{collection_name}' 已存在,正在删除...")
    utility.drop_collection(collection_name)

# 2. 定义集合模式(向量+元数据)
fields = [
    FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
    FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=128),
    FieldSchema(name="title", dtype=DataType.VARCHAR, max_length=200)
]
schema = CollectionSchema(fields, description="news collection")
collection = Collection("my_news", schema)

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

# 4. 插入数据
# 生成10000条模拟数据
num_records = 10000
ids = list(range(num_records))
embeddings = np.random.random((num_records, 128)).tolist()
titles = [f"title_{i}" for i in range(num_records)]

# 准备插入数据
data = [embeddings, titles]
collection.insert(data)

# 将集合加载到内存
collection.load()

# 5. 混合搜索(向量相似度 + 标量过滤)
# 首先创建查询向量(这里随机生成一个查询向量)
query_vector = np.random.random((1, 128)).tolist()  # 单个查询向量

# 设置搜索参数
search_params = {"metric_type": "L2", "params": {"ef": 100}}

# 执行搜索
results = collection.search(
    data=query_vector,  # 查询向量
    anns_field="embedding",  # 向量字段名
    param=search_params,  # 搜索参数
    limit=10,  # 返回结果数量
    expr="title like 'title_5%'"  # 标量过滤条件
)

# 输出搜索结果
print("搜索结果:")
for hits in results:
    for hit in hits:
        print(f"id: {hit.id}, 距离: {hit.distance}, 标题: {hit.entity.get('title')}")

# 6. 清理资源(可选)
# collection.drop()

# 停止服务器(可选)
# default_server.stop()

结果:

bash 复制代码
集合 'my_news' 已存在,正在删除...
搜索结果:
id: 463685161034454964, 距离: 15.321002006530762, 标题: None
id: 463685161034454646, 距离: 15.373628616333008, 标题: None
id: 463685161034454432, 距离: 15.433990478515625, 标题: None
id: 463685161034454209, 距离: 15.609135627746582, 标题: None
id: 463685161034454146, 距离: 15.669434547424316, 标题: None
id: 463685161034454907, 距离: 15.885712623596191, 标题: None
id: 463685161034454823, 距离: 15.902074813842773, 标题: None
id: 463685161034454500, 距离: 16.118179321289062, 标题: None
id: 463685161034454563, 距离: 16.18042755126953, 标题: None
id: 463685161034454598, 距离: 16.20553207397461, 标题: None
  • 适用场景: 生产级AI应用(如RAG、内容推荐、欺诈检测),需要管理海量向量和元数据,并追求高可用和可扩展性。
3. Elasticsearch (v7.x+)

定位在传统全文搜索引擎基础上扩展了向量搜索能力的通用搜索平台。

  • 核心特性
    • 混合搜索 : 将向量搜索关键词搜索过滤器聚合分析无缝结合能力是其最大优势。
    • 强大的生态: 成熟的ELK栈,提供日志、监控、安全等全方位企业级功能。
    • 数据管理: 本身就是成熟的文档数据库,具备完整的数据管理、分布式和高可用能力。
    • 向量能力 : 从7.x版本开始支持dense_vector类型,并内置HNSW索引支持。
  • 部署与使用
    • 部署: 通过Docker、tar包或云服务部署Elasticsearch集群。
    • 典型使用流程

(1)创建带向量字段的映射: 在Elasticsearch中创建一个名为"my_index"的索引,并定义其映射(mapping)。映射中指定了索引中文档的字段及其类型和属性。

bash 复制代码
PUT my_index
{
  "mappings": {
    "properties": {
      "content": { "type": "text" },
      "embedding": { 
        "type": "dense_vector",
        "dims": 128,
        "index": true,
        "similarity": "cosine",
        "index_options": {
          "type": "hnsw",
          "m": 16,
          "ef_construction": 200
        }
      }
    }
  }
}

具体来说,这个映射定义了两个字段:

  1. "content"字段:类型为"text",这意味着它是一个文本字段,会进行分词处理,用于全文搜索。
  2. "embedding"字段:类型为"dense_vector",这是一个密集向量类型,用于存储向量数据。这里指定了向量的维度(dims)为128,并且设置了该字段将被索引(index: true)以便进行相似度搜索。相似度度量方式为余弦相似度(cosine)。此外,还指定了索引选项(index_options)使用HNSW(Hierarchical Navigable Small World)算法进行近似最近邻搜索,其中参数m(构建图时每个节点连接的边数)设置为16,ef_construction(构建图时考虑的候选节点数量)设置为200。

总结:这段代码创建了一个用于向量相似度搜索的索引,可以存储文本内容和对应的128维向量,并支持使用余弦相似度进行近似最近邻搜索。

(2)插入文档 : 像插入普通JSON文档一样,包含embedding字段。

(3)执行混合搜索

bash 复制代码
GET my_index/_search
{
  "query": {
    "script_score": {
      "query": { "match": { "content": "机器学习" } },  // 文本查询
      "script": {
        "source": "cosineSimilarity(params.query_vector, 'embedding') + 1.0",
        "params": { "query_vector": [0.12, 0.34, ...] }
      }
    }
  }
}

检索主要步骤:

  1. 首先,使用一个基础的文本查询(match query)在"content"字段中查找包含"机器学习"的文档。这一步会得到一个基础查询的分数。
  2. 然后,使用脚本(script)计算每个文档的向量字段(embedding)与给定查询向量(query_vector)的余弦相似度,并加1.0(为了避免负分)。
  3. 最后,将基础查询的分数与脚本计算出的余弦相似度分数相乘(script_score的默认操作是相乘)得到每个文档的最终分数。
  • 适用场景 : 已在使用ES生态,或对文本+向量的混合搜索需求极强的应用(如电商搜索、企业知识库、日志分析)。

第三部分:理解索引结构 - HNSW

HNSW是当前最流行、综合性能最佳的ANN索引之一,被Faiss、Milvus、Elasticsearch等广泛采用。

1. 核心思想:分层可导航小世界
  • 小世界网络: 灵感来自社交网络(六度分隔理论)。在这种网络中,任意两个节点都可以通过少量几步连接。通过构建这种网络,可以在搜索时快速"跳跃"到目标区域。
  • 分层结构: 构建一个多层的图结构(类似跳表)。底层(第0层)包含所有数据点,越往上,节点越稀疏,连接是长距离的"高速公路"。
2. 构建过程(插入)
  1. 随机选择层数 : 为新插入的节点q分配一个最高层l(指数衰减概率分布,确保高层节点极少)。
  2. 从顶层开始查找
    • 从顶层的一个入口点开始。
    • 在当前层,贪婪地移动到最接近q的邻居节点,直到无法更接近。
  3. 逐层向下搜索并连接
    • 重复步骤2,直到达到第l层。
    • 在第l层找到qefConstruction个最近邻,然后将q与这些邻居中的一部分(由M参数控制最大连接数)建立双向连接。
3. 搜索过程(查询)
  1. 从顶层入口点开始
  2. 贪婪遍历: 在当前层,从当前已知的最近邻集合中,不断移动到更接近查询目标的邻居,直到局部最优。
  3. 进入下一层: 将当前层的局部最优结果作为下一层的入口点,重复步骤2。
  4. 在底层进行精细搜索 : 到达第0层后,使用一个动态候选列表(大小为efSearch)进行更精细的搜索,最终返回列表中的最近邻。
4. 关键参数
  • M: 每个节点在第0层以上的最大连接数。值越大,图越稠密,精度越高,但内存占用和构建时间也增加。
  • efConstruction: 构建时动态候选列表的大小。值越大,构建质量越高,构建越慢。
  • efSearch: 搜索时动态候选列表的大小。值越大,搜索精度越高,搜索越慢。

直观比喻: 查找一本图书馆的书。

  • Flat(暴力搜索): 从第一排书架开始,逐本比对。
  • HNSW : 先看楼层索引(顶层),找到"科技类"区域(快速跳跃),再看"计算机"分区(中层),最后在"AI书籍"书架(底层)仔细寻找。efSearch决定了你在最终书架上要仔细翻看多少本书后才做决定。

第四部分:对比与总结

|-------------|--------------|-----------------|---------------------|
| 特性 | Faiss | Milvus | Elasticsearch |
| 定位 | 搜索引擎库 | 向量数据库 | 通用搜索平台 |
| 核心优势 | 极致性能,算法灵活 | 功能完备,云原生,可扩展 | 文本+向量混合搜索,生态强大 |
| 数据管理 | 无 | 强(CRUD,元数据) | 强(文档数据库) |
| 持久化/高可用 | 需自行处理 | 内置 | 内置 |
| 部署复杂度 | 极低(库) | 中等(Docker/K8s) | 中等(集群) |
| 学习成本 | 低(API简单) | 中(概念较多) | 高(DSL复杂,生态庞大) |
| 典型场景 | 算法研究,嵌入到其他系统 | 生产AI应用,RAG,AIGC | 企业搜索,混合检索,已有ES生态的应用 |

如何选择?

  1. 追求简单、高性能的离线或嵌入式场景 : 选择Faiss
  2. 构建全新的、以向量为中心的AI应用,需要生产级特性 : 选择Milvus
  3. 已有Elasticsearch,或对关键词与向量的混合搜索需求是核心 : 选择Elasticsearch
  4. 学习入门 : 可以从Faiss 开始理解向量搜索的基本原理,然后转向Milvus以了解完整的向量数据库概念。
相关推荐
悟能不能悟2 小时前
查找oracle,存储过程包含某个单词的存储过程名称
数据库·oracle
马克学长2 小时前
SSM学生综合考评系统b8vlm(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架·学生综合考评系统·高校学生管理、
独自破碎E3 小时前
MySQL中如何进行SQL调优?
数据库·sql·mysql
laplace01233 小时前
第八章 agent记忆与检索 下
数据库·人工智能·笔记·agent·rag
MyselfO(∩_∩)O3 小时前
1148. 文章浏览 I
数据库
少云清3 小时前
【性能测试】10_JMeter _JMeter连接数据库(重点)
数据库·jmeter
程序员敲代码吗3 小时前
使用Python进行PDF文件的处理与操作
jvm·数据库·python
小光学长4 小时前
基于SSM的个人健康系统26vxdh02(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库
mit6.8244 小时前
sql窗口函数
数据库