Skip to content

向量数据库概述

什么是向量数据库?

向量数据库是专门用于存储、管理和查询高维向量的数据库系统。在AI应用中,向量数据库主要用于存储文本、图像等数据的向量表示,并支持高效的相似性搜索。

核心概念

1. 向量表示

向量表示是将非结构化数据(文本、图像等)转换为固定长度的数值向量:

  • 嵌入模型:将数据转换为向量的模型
  • 向量维度:向量的维度大小(如768维、1536维)
  • 语义信息:向量包含数据的语义信息
  • 相似性计算:通过向量距离计算相似性

2. 相似性搜索

相似性搜索是向量数据库的核心功能:

  • 距离度量:余弦相似度、欧氏距离、内积等
  • 近似最近邻(ANN):高效的近似搜索算法
  • 精确搜索:暴力搜索,准确但慢
  • 过滤搜索:基于元数据的过滤

3. 索引结构

索引结构决定搜索效率:

  • HNSW:分层可导航小世界图
  • IVF:倒排文件索引
  • PQ:乘积量化
  • Annoy:近似最近邻哦yeah

4. 数据管理

向量数据库的数据管理功能:

  • CRUD操作:创建、读取、更新、删除
  • 元数据存储:存储向量相关的元数据
  • 批量操作:支持批量插入和查询
  • 持久化:数据持久化存储

应用场景

1. RAG系统

  • 文档检索:检索相关文档片段
  • 知识库问答:基于知识库的问答系统
  • 内容推荐:推荐相似内容

2. 图像搜索

  • 以图搜图:相似图像搜索
  • 图像分类:基于向量的图像分类
  • 目标检测:相似目标检索

3. 推荐系统

  • 商品推荐:相似商品推荐
  • 内容推荐:相似内容推荐
  • 用户画像:基于向量的用户相似度

4. 语义搜索

  • 语义理解:理解查询的语义意图
  • 模糊匹配:模糊文本匹配
  • 跨语言搜索:跨语言语义搜索

技术原理

1. 向量空间模型

向量空间模型的基本原理:

  • 向量表示:将数据表示为高维向量
  • 语义相似:语义相似的数据在向量空间中距离较近
  • 距离度量:通过距离度量计算相似性
  • 聚类分析:基于向量的聚类分析

2. 近似最近邻搜索

ANN搜索的核心算法:

  • 树结构:KD树、Ball树等
  • 图结构:HNSW、NSG等
  • 哈希方法:局部敏感哈希(LSH)
  • 量化方法:乘积量化(PQ)

3. 分布式架构

大规模向量数据库的架构:

  • 分片机制:数据分片存储
  • 副本机制:数据副本备份
  • 负载均衡:查询负载均衡
  • 一致性保证:数据一致性保证

选型指南

1. 功能需求

  • 搜索精度:精确搜索还是近似搜索
  • 搜索速度:响应时间要求
  • 数据规模:数据量大小
  • 功能需求:是否需要过滤、排序等

2. 性能需求

  • 查询延迟:查询响应时间要求
  • 吞吐量:每秒查询数要求
  • 并发能力:并发查询支持
  • 资源消耗:CPU、内存、存储资源

3. 部署需求

  • 部署方式:本地部署、云服务、容器化
  • 扩展性:水平扩展能力
  • 运维成本:运维复杂度和成本
  • 生态集成:与现有系统的集成

技术方案对比

主流向量数据库全面对比

数据库类型语言索引类型最大数据量部署方式适用场景
Pinecone云服务Python专有无限制全托管生产环境、快速上线
Weaviate开源GoHNSW无限制自托管/云复杂查询、多模态
Milvus开源Go/C++多种无限制自托管/云大规模生产环境
Chroma开源PythonHNSW百万级嵌入式原型开发、小规模
Qdrant开源RustHNSW无限制自托管/云高性能需求
FAISSC++多种十亿级嵌入式研究、本地使用
pgvector扩展CIVF/HNSW百万级PostgreSQL扩展已有PG环境
Redis扩展CHNSW百万级Redis模块已有Redis环境
Elasticsearch扩展JavaHNSW十亿级ES插件已有ES环境

如何选择向量数据库?

选择流程:

数据规模?
├── 小于100万 → Chroma/FAISS(简单易用)
├── 100万-1000万 → Qdrant/Weaviate(性能好)
└── 大于1000万 → Milvus/Pinecone(可扩展)

部署要求?
├── 快速上线 → Pinecone(全托管)
├── 已有PostgreSQL → pgvector
├── 已有Redis → Redis Vector
└── 需要自托管 → Milvus/Qdrant

功能需求?
├── 简单向量搜索 → FAISS/Chroma
├── 复杂过滤 → Weaviate/Qdrant
├── 多模态 → Weaviate
└── 混合搜索 → Elasticsearch

场景选型建议

场景推荐数据库原因
快速原型Chroma轻量级、易上手
小团队生产Qdrant高性能、易部署
大规模生产Milvus分布式、可扩展
全托管服务Pinecone无需运维
已有PostgreSQLpgvector无需额外组件
复杂查询WeaviateGraphQL接口、多模态
研究实验FAISSFacebook开源、功能强大

设计原理与目的

为什么需要向量数据库?

传统数据库的局限:

问题:如何搜索语义相似的文本?

传统数据库(关键词匹配):
SELECT * FROM documents 
WHERE content LIKE '%人工智能%'

问题:
1. 只能精确匹配关键词
2. 无法理解语义("AI"和"人工智能"是同义词)
3. 无法处理同义词、近义词

向量数据库的优势:

向量数据库(语义搜索):
1. 将文本转换为向量(理解语义)
2. 计算向量相似度(语义匹配)
3. 返回语义最相似的结果

示例:
查询:"AI技术" 
可以找到:"人工智能技术"、"机器学习"、"深度学习"

向量相似度计算原理

1. 余弦相似度(最常用)

原理:计算两个向量的夹角余弦值
公式:cos(A, B) = (A·B) / (|A|×|B|)
范围:[-1, 1],越接近1越相似

示例:
A = [1, 0, 1]
B = [1, 1, 0]
cos(A, B) = (1×1 + 0×1 + 1×0) / (√2 × √2) = 1/2 = 0.5

2. 欧氏距离

原理:计算两个向量的直线距离
公式:d(A, B) = √(Σ(Ai-Bi)²)
范围:[0, +∞),越小越相似

示例:
A = [1, 0, 1]
B = [1, 1, 0]
d(A, B) = √((1-1)² + (0-1)² + (1-0)²) = √2 ≈ 1.41

3. 内积

原理:计算两个向量的点积
公式:A·B = Σ(Ai×Bi)
范围:越大越相似(需归一化)

示例:
A = [1, 0, 1]
B = [1, 1, 0]
A·B = 1×1 + 0×1 + 1×0 = 1

索引结构原理

为什么需要索引?

问题:100万向量,每个1536维
暴力搜索:需要计算100万次相似度
耗时:约1秒(太慢)

解决方案:使用索引结构
索引后:只需要计算几千次
耗时:约1毫秒(快1000倍)

HNSW索引原理:

HNSW = 分层可导航小世界图

类比:像高速公路网络
- 高层:长距离连接,快速定位大致区域
- 中层:中距离连接,缩小搜索范围
- 低层:短距离连接,精确找到最近邻

搜索过程:
1. 从高层开始
2. 跳转到最近的节点
3. 逐层下降,范围缩小
4. 在低层找到精确结果

IVF索引原理:

IVF = 倒排文件索引

类比:像图书馆分类
- 先将向量分成多个聚类(类似图书分类)
- 搜索时只在相关聚类中查找
- 大大减少搜索范围

搜索过程:
1. 计算查询向量属于哪个聚类
2. 只在该聚类中搜索
3. 返回最近邻结果

为什么选择这些索引?

索引类型构建时间搜索速度内存占用适用场景
Flat小数据集、精确搜索
HNSW通用场景、高精度需求
IVF中等大数据集、内存受限
PQ很低超大规模、内存极度受限

应用场景详解

场景一:RAG知识库

需求: 企业内部知识库问答

实现:

python
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 1. 准备文档
documents = [
    "公司年假政策:员工入职满1年后享受5天年假...",
    "报销流程:员工提交报销申请后,需经过部门经理审批...",
    "考勤制度:工作时间为上午9点到下午6点..."
]

# 2. 创建向量数据库
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_texts(documents, embeddings)

# 3. 搜索
results = vectorstore.similarity_search("年假有几天?", k=1)
print(results[0].page_content)

场景二:商品推荐系统

需求: 根据用户浏览的商品推荐相似商品

实现:

python
from qdrant_client import QdrantClient
from qdrant_client.models import VectorParams, Distance, PointStruct
from openai import OpenAI

# 1. 初始化
client = QdrantClient(path="./qdrant_data")
openai_client = OpenAI(api_key="your-api-key")

# 2. 创建集合
client.create_collection(
    collection_name="products",
    vectors_config=VectorParams(size=1536, distance=Distance.COSINE)
)

# 3. 添加商品
def get_embedding(text):
    response = openai_client.embeddings.create(
        model="text-embedding-ada-002",
        input=text
    )
    return response.data[0].embedding

products = [
    {"id": 1, "name": "iPhone 15", "desc": "苹果最新手机,A17芯片"},
    {"id": 2, "name": "MacBook Pro", "desc": "苹果笔记本电脑,M3芯片"},
    {"id": 3, "name": "AirPods Pro", "desc": "苹果无线耳机,主动降噪"}
]

points = []
for product in products:
    embedding = get_embedding(product["desc"])
    points.append(PointStruct(
        id=product["id"],
        vector=embedding,
        payload=product
    ))

client.upsert(collection_name="products", points=points)

# 4. 推荐相似商品
def recommend_similar(product_name, top_k=3):
    # 获取商品描述
    product = next(p for p in products if p["name"] == product_name)
    query_vector = get_embedding(product["desc"])
    
    # 搜索相似商品
    results = client.search(
        collection_name="products",
        query_vector=query_vector,
        limit=top_k + 1  # 多取一个,排除自己
    )
    
    # 排除自己
    return [r for r in results if r.id != product["id"]][:top_k]

# 使用示例
recommendations = recommend_similar("iPhone 15")
for rec in recommendations:
    print(f"推荐:{rec.payload['name']} - {rec.payload['desc']}")

场景三:图像搜索系统

需求: 以图搜图,找到相似图片

实现:

python
from qdrant_client import QdrantClient
from qdrant_client.models import VectorParams, Distance, PointStruct
import torch
from torchvision import models, transforms
from PIL import Image

# 1. 加载预训练模型
model = models.resnet50(pretrained=True)
model.eval()

# 图像预处理
transform = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])

def get_image_embedding(image_path):
    """获取图像嵌入向量"""
    image = Image.open(image_path)
    image_tensor = transform(image).unsqueeze(0)
    
    with torch.no_grad():
        # 使用倒数第二层作为特征
        features = model.avgpool(model.layer4(model.layer3(model.layer2(model.layer1(
            model.maxpool(model.relu(model.bn1(model.conv1(image_tensor)))))
        ))))
        embedding = features.flatten().numpy().tolist()
    
    return embedding

# 2. 创建向量数据库
client = QdrantClient(path="./image_qdrant")
client.create_collection(
    collection_name="images",
    vectors_config=VectorParams(size=2048, distance=Distance.COSINE)
)

# 3. 添加图像
images = [
    {"id": 1, "path": "cat1.jpg", "label": "猫咪"},
    {"id": 2, "path": "dog1.jpg", "label": "小狗"},
    {"id": 3, "path": "cat2.jpg", "label": "猫咪"}
]

points = []
for img in images:
    embedding = get_image_embedding(img["path"])
    points.append(PointStruct(
        id=img["id"],
        vector=embedding,
        payload=img
    ))

client.upsert(collection_name="images", points=points)

# 4. 搜索相似图像
def search_similar_images(query_image_path, top_k=3):
    query_embedding = get_image_embedding(query_image_path)
    
    results = client.search(
        collection_name="images",
        query_vector=query_embedding,
        limit=top_k
    )
    
    return results

# 使用示例
results = search_similar_images("query_cat.jpg")
for result in results:
    print(f"相似度: {result.score:.2f}, 标签: {result.payload['label']}")

场景四:混合搜索

需求: 结合关键词和语义的搜索

实现:

python
from elasticsearch import Elasticsearch
from openai import OpenAI
import numpy as np

# 1. 初始化
es = Elasticsearch("http://localhost:9200")
openai_client = OpenAI(api_key="your-api-key")

# 2. 创建索引(支持向量和文本)
mapping = {
    "mappings": {
        "properties": {
            "content": {"type": "text"},
            "embedding": {
                "type": "dense_vector",
                "dims": 1536,
                "index": True,
                "similarity": "cosine"
            }
        }
    }
}

es.indices.create(index="documents", body=mapping)

# 3. 添加文档
def add_document(doc_id, content):
    # 获取嵌入向量
    response = openai_client.embeddings.create(
        model="text-embedding-ada-002",
        input=content
    )
    embedding = response.data[0].embedding
    
    # 添加到Elasticsearch
    es.index(
        index="documents",
        id=doc_id,
        body={
            "content": content,
            "embedding": embedding
        }
    )

# 添加示例文档
add_document(1, "人工智能是计算机科学的一个分支")
add_document(2, "机器学习是人工智能的子领域")
add_document(3, "深度学习是机器学习的一种方法")

# 4. 混合搜索
def hybrid_search(query, alpha=0.5):
    """混合搜索:结合关键词和语义"""
    # 获取查询嵌入
    response = openai_client.embeddings.create(
        model="text-embedding-ada-002",
        input=query
    )
    query_embedding = response.data[0].embedding
    
    # 构建混合查询
    search_query = {
        "query": {
            "bool": {
                "must": [
                    {"match": {"content": query}}  # 关键词匹配
                ]
            }
        },
        "knn": {
            "field": "embedding",
            "query_vector": query_embedding,
            "k": 3,
            "num_candidates": 10
        }
    }
    
    results = es.search(index="documents", body=search_query)
    return results["hits"]["hits"]

# 使用示例
results = hybrid_search("AI技术")
for result in results:
    print(f"分数: {result['_score']}, 内容: {result['_source']['content']}")

主流向量数据库对比

数据库类型语言索引特点适用场景
Pinecone云服务Python专有全托管、易用生产环境、快速上线
Weaviate开源GoHNSW多模态、GraphQL复杂查询、多模态
Milvus开源Go/C++多种高性能、分布式大规模生产环境
Chroma开源PythonHNSW轻量级、嵌入式原型开发、小规模
Qdrant开源RustHNSW高性能、Rust编写高性能需求
FAISSC++多种Facebook开源研究、本地使用
pgvector扩展CIVFPostgreSQL扩展已有PG环境
Redis扩展CHNSWRedis模块已有Redis环境
Elasticsearch扩展JavaHNSWES插件已有ES环境

选择建议

1. 原型开发

  • Chroma:轻量级,易于上手
  • FAISS:本地使用,无需部署

2. 小规模生产

  • Qdrant:高性能,易于部署
  • Weaviate:功能丰富,社区活跃

3. 大规模生产

  • Milvus:分布式架构,高性能
  • Pinecone:全托管,无需运维

4. 特定环境

  • pgvector:已有PostgreSQL环境
  • Redis:已有Redis环境
  • Elasticsearch:已有ES环境

性能优化

1. 索引优化

  • 选择合适的索引结构:根据数据特点选择
  • 调整索引参数:优化索引构建参数
  • 定期重建索引:数据变化后重建索引

2. 查询优化

  • 合理的K值:选择合适的返回数量
  • 过滤优化:合理使用元数据过滤
  • 缓存机制:缓存热点查询

3. 存储优化

  • 向量量化:降低存储空间
  • 数据压缩:压缩存储数据
  • 分层存储:热数据和冷数据分层

常见问题

1. 准确性问题

  • 召回率低:调整索引参数,增加搜索范围
  • 精度低:使用更精确的索引结构
  • 噪声影响:预处理数据,减少噪声

2. 性能问题

  • 查询慢:优化索引,增加缓存
  • 内存占用高:使用量化,压缩向量
  • 扩展性差:选择分布式架构

3. 运维问题

  • 数据备份:定期备份数据
  • 监控告警:设置监控和告警
  • 版本升级:平滑升级版本

深入学习

向量数据库详细文档

选择一个向量数据库深入学习:

数据库特点适用场景详细文档
Chroma轻量级、Python原生原型开发、学习Chroma详解
FAISSFacebook开源、GPU加速研究、高性能本地FAISS详解
Milvus云原生、分布式大规模生产Milvus详解
QdrantRust实现、高性能中小规模生产Qdrant详解
Weaviate多模态、GraphQL多模态应用Weaviate详解
Pinecone全托管、零运维快速上线Pinecone详解
pgvectorPostgreSQL扩展已有PG环境pgvector详解

向量数据库深度对比

查看详细的对比分析:向量数据库深度对比

对比内容包括:

  • 性能基准测试对比
  • 功能特性对比(混合搜索、多模态、事务支持)
  • 可扩展性对比
  • 运维复杂度对比
  • 选型建议

下一步学习