共计 3801 个字符,预计需要花费 10 分钟才能阅读完成。
1. 背景介绍
传统关系型数据库在处理结构化数据时表现出色,但当我们需要处理高维向量数据时(比如图像特征、文本嵌入、用户偏好向量等),传统数据库就显得力不从心了。

向量数据库是专门为存储和查询向量数据而设计的数据库系统,它能够高效地执行相似度搜索,找到与查询向量最相似的向量。这在推荐系统、图像搜索、自然语言处理等领域有着广泛应用。
为什么需要向量数据库?
- 高效相似度搜索:传统数据库无法高效执行 ” 找到与这个向量最相似的 10 个向量 ” 这样的查询
- 高维数据处理:向量通常有几百甚至几千个维度,传统索引方法不适用
- 实时性能:专业向量数据库针对向量查询做了大量优化
2. 核心概念
2.1 向量嵌入(Vector Embedding)
向量嵌入是将现实世界的数据(如文本、图像)转换为固定长度的数值向量的过程。例如:
- 一段文本可以通过 BERT 等模型转换为 768 维的向量
- 一张图片可以通过 ResNet 转换为 2048 维的特征向量
2.2 相似度计算
衡量两个向量相似度的常用方法:
余弦相似度(Cosine Similarity)
计算两个向量之间夹角的余弦值,范围[-1,1],值越大越相似。
公式:
cos(θ) = (A·B) / (||A|| * ||B||)
欧式距离(Euclidean Distance)
计算两个向量之间的直线距离,值越小越相似。
公式:
√Σ(Ai - Bi)²
2.3 近似最近邻搜索(ANN)
精确计算所有向量的相似度在大数据量时性能很差,ANN 算法通过牺牲少量精度换取查询速度的大幅提升。常见算法:
- HNSW (Hierarchical Navigable Small World)
- IVF (Inverted File Index)
- LSH (Locality-Sensitive Hashing)
3. 技术实现:C# 内存向量数据库
下面我们实现一个简单的内存向量数据库,支持基本的 CRUD 和相似度搜索功能。
3.1 数据结构设计
public class VectorItem
{public string Id { get; set;}
public float[] Vector { get; set;}
public Dictionary<string, object> Metadata {get; set;} = new();}
public class SimpleVectorDatabase
{private readonly List<VectorItem> _items = new();
private readonly int _dimensions;
public SimpleVectorDatabase(int dimensions)
{_dimensions = dimensions;}
}
3.2 相似度计算实现
public static class VectorMath
{public static float CosineSimilarity(float[] a, float[] b)
{if (a.Length != b.Length)
throw new ArgumentException("Vectors must be of same length");
float dot = 0.0f, magA = 0.0f, magB = 0.0f;
for (int i = 0; i < a.Length; i++)
{dot += a[i] * b[i];
magA += a[i] * a[i];
magB += b[i] * b[i];
}
return dot / (MathF.Sqrt(magA) * MathF.Sqrt(magB));
}
public static float EuclideanDistance(float[] a, float[] b)
{if (a.Length != b.Length)
throw new ArgumentException("Vectors must be of same length");
float sum = 0.0f;
for (int i = 0; i < a.Length; i++)
{float diff = a[i] - b[i];
sum += diff * diff;
}
return MathF.Sqrt(sum);
}
}
3.3 CRUD 操作实现
public class SimpleVectorDatabase
{
// ... 前面的代码
public void Add(VectorItem item)
{if (item.Vector.Length != _dimensions)
throw new ArgumentException($"Vector must have {_dimensions} dimensions");
_items.Add(item);
}
public VectorItem Get(string id)
{return _items.FirstOrDefault(x => x.Id == id);
}
public void Update(VectorItem item)
{var existing = Get(item.Id);
if (existing != null)
{
existing.Vector = item.Vector;
existing.Metadata = item.Metadata;
}
}
public void Delete(string id)
{_items.RemoveAll(x => x.Id == id);
}
}
3.4 相似度搜索实现
public class SimpleVectorDatabase
{
// ... 前面的代码
public IEnumerable<(VectorItem Item, float Score)> Search(float[] queryVector,
int limit = 10,
Func<float[], float[], float> similarityMetric = null)
{if (queryVector.Length != _dimensions)
throw new ArgumentException($"Query vector must have {_dimensions} dimensions");
similarityMetric ??= VectorMath.CosineSimilarity;
return _items
.Select(item => (Item: item, Score: similarityMetric(queryVector, item.Vector)))
.OrderByDescending(x => x.Score)
.Take(limit);
}
}
4. 完整代码示例
using System;
using System.Collections.Generic;
using System.Linq;
namespace VectorDatabaseDemo
{
class Program
{static void Main(string[] args)
{
// 创建一个 3 维的向量数据库
var db = new SimpleVectorDatabase(3);
// 添加一些向量
db.Add(new VectorItem {
Id = "item1",
Vector = new[] { 1.0f, 2.0f, 3.0f},
Metadata = new Dictionary<string, object> {{ "name", "红苹果"}, {"category", "水果"} }
});
db.Add(new VectorItem {
Id = "item2",
Vector = new[] { 4.0f, 5.0f, 6.0f},
Metadata = new Dictionary<string, object> {{ "name", "香蕉"}, {"category", "水果"} }
});
// 搜索相似的向量
var query = new[] { 1.1f, 2.1f, 2.9f};
var results = db.Search(query);
Console.WriteLine("最相似的结果:");
foreach (var result in results)
{Console.WriteLine($"ID: {result.Item.Id}, 相似度: {result.Score}, 名称: {result.Item.Metadata["name"]}");
}
}
}
}
5. 性能考量
我们这个简单实现有几个性能问题:
- 线性扫描:每次查询都需要计算所有向量的相似度,时间复杂度 O(N)
- 内存限制:所有数据保存在内存中,不适合大数据量
- 无并行化:查询过程是单线程的
对于生产环境,当数据量超过几千条时,这种简单实现就会遇到性能瓶颈。
6. 生产环境建议
当你的应用需要:
- 存储数百万以上向量
- 低延迟查询(<100ms)
- 高查询吞吐量
- 分布式部署
就应该考虑使用专业向量数据库,如:
- Milvus:开源的向量数据库,功能全面
- Pinecone:全托管的向量数据库服务
- Weaviate:支持向量搜索的图数据库
- Qdrant:高性能 Rust 实现的向量数据库
7. 进阶学习指引
- 向量索引算法:深入学习 HNSW、IVF 等近似最近邻算法
- 向量压缩技术 :如 PQ(Product Quantization) 减少内存占用
- 混合查询:结合向量搜索和传统过滤条件
- 分布式向量数据库:学习如何水平扩展向量数据库
实践建议
- 尝试用真实数据(如商品图片特征)测试我们的简单实现
- 添加持久化功能,将向量数据保存到文件
- 实现批处理接口,支持批量添加向量
- 尝试集成一个开源 ANN 库(如 FAISS)来替换线性扫描
希望这篇入门教程能帮助你理解向量数据库的核心概念和基本实现。在实际项目中,根据数据规模和性能需求选择合适的解决方案。
正文完
