什么是向量数据库?

我们每天生成的数百万兆字节的数据中,大多数是非结构化的。想想你拍的餐食照片、工作中分享的PDF文件,或者你保存但可能永远不会听的播客。这些数据都不能整齐地适应行和列。
非结构化数据缺乏严格的格式或模式,这使得传统数据库难以管理。然而,这种非结构化数据对人工智能、机器学习以及现代搜索引擎具有巨大的潜力。
一个 向量数据库 是一个专门的系统,旨在高效处理高维向量数据。它在索引、查询和检索这些数据方面表现优秀,使得传统数据库无法轻易执行的高级分析和相似性搜索成为可能。
传统数据库面临的挑战
传统的 在线事务处理 和 OLAP 数据库在数据存储方面已经存在数十年。它们非常擅长管理具有明确架构的结构化数据,如 name, address, phone number 和 purchase history。

但是当数据无法被轻易分类时,比如PDF文件中的内容,事情就开始变得复杂。
您可以始终将PDF文件存储为原始数据,也许附带一些元数据。然而,数据库仍然无法理解文档内部的内容,无法对其进行分类,甚至无法搜索其中包含的信息。
此外,这不仅适用于PDF文档。考虑一下你每天生成的大量文本、音频和图像数据。如果数据库无法理解这些数据的含义,那么你如何在数据中搜索或发现关系呢?

向量数据库允许您通过将非结构化数据表示为向量来理解上下文或概念相似性,从而实现基于数据相似性的高级分析和检索。
何时使用向量数据库
不确定是否应该使用向量数据库还是传统数据库?这个图表可能会有所帮助。
| 特性 | 在线交易处理数据库 | 在线分析处理数据库 | 向量数据库 |
|---|---|---|---|
| 数据结构 | 行和列 | 行和列 | 向量 |
| 数据类型 | 结构化 | 结构化/部分结构化 | 非结构化 |
| 查询方法 | 基于SQL(事务查询) | 基于SQL(聚合,分析查询) | 向量搜索(基于相似性) |
| 存储聚焦 | 基于模式,优化用于更新 | 基于模式,优化用于读取 | 上下文和语义 |
| 性能 | 针对高交易量进行了优化 | 针对复杂分析查询进行了优化 | 针对非结构化数据检索进行了优化 |
| 使用案例 | 库存,订单处理,客户关系管理 | 商业智能,数据仓库 | 相似性搜索,推荐,RAG,异常检测等 |
什么是向量?

当机器需要处理非结构化数据 - 一张图片、一段文本或一个音频文件时,它首先必须将这些数据转换为可以处理的格式:向量。
一个 向量 是数据的数值表示,可以捕捉数据的 上下文 和 语义。
当你处理非结构化数据时,传统数据库很难理解其含义。然而,向量可以将这些数据转换为机器可以处理的内容。例如,从文本生成的向量可以表示单词之间的关系和含义,使机器能够比较和理解它们的上下文。
向量数据库中定义向量的三个关键元素是:ID、维度和负载。这些组件共同作用,在系统中有效地表示一个向量。它们共同形成一个点,这是在向量数据库中存储和检索数据的核心单位。

这些部分在向量的存储、检索和解释中扮演着重要的角色。让我们来看看。
1. ID:您的向量独特标识符
就像在关系数据库中,向量数据库中的每个向量都有一个唯一的ID。把它想象成你向量的姓名标签,一个主键,确保可以轻松找到该向量。当向量被添加到数据库中时,ID会自动创建。
虽然 ID 本身在相似性搜索中并不发挥作用(该搜索操作基于向量的数值数据),但它对于将向量与其对应的“现实世界”数据(无论是文档、图像还是声音文件)关联起来是至关重要的。
在执行搜索并找到相似向量后,将返回它们的ID。这些ID可以用来提取与结果相关的其他详细信息或元数据。
2. 维度:数据的核心表示
每个向量的核心是一组数字,这些数字共同形成在多维空间中数据的表示。
从文本到向量:它是如何工作的?
这些数字是由 嵌入模型 生成的,例如深度学习算法,并捕捉数据中的基本模式或关系。这就是为什么术语 嵌入 在提到这些模型的输出时常常与向量可以互换使用。
为了表示文本数据,例如,嵌入将在其维度内封装语言的细微差别,例如语义和上下文。

因此,当比较两个相似的句子时,它们的嵌入会变得非常相似,因为它们具有相似的 语言元素。

这就是嵌入的美。数据的复杂性被提炼成可以在多维空间中进行比较的东西。
3. 载荷:通过元数据添加上下文
有时候,仅仅依靠数字不足以完全理解或完善搜索。虽然维度捕捉了数据的本质,但有效载荷包含元数据用于结构化信息。
它可以是文本数据,如描述、标签、类别,或者它可以是数值,如日期或价格。这个额外的信息在你想根据直接未编码在向量中的标准来筛选或排序搜索结果时是至关重要的。
当您需要应用额外的 过滤器 或 排序 标准时,这些元数据是非常宝贵的。
例如,如果您正在搜索一张狗的图片,向量可以帮助数据库找到视觉上相似的图像。但是假设您想要的结果仅显示在过去一年内拍摄的图像,或者那些标记为“度假”的图像。

负载可以帮助您缩小结果范围,忽略不符合查询向量过滤标准的向量。如果您想全面了解Qdrant中过滤的工作原理,请查看我们的 完整过滤指南。
向量数据库的架构
向量数据库由多个不同的实体和关系构成。让我们了解一下这里发生了什么:
集合
一个 集合 本质上是一组 向量(或“点”),它们在逻辑上基于 相似性或特定任务 组合在一起。每个集合中的向量具有相同的维度,并且可以使用单一指标进行比较。除非必要,否则避免创建多个集合;相反,可以考虑使用 分片 技术来在节点之间进行扩展,或使用 多租户 技术来处理同一基础架构中的不同用例。
距离度量
这些度量定义了如何计算向量之间的相似性。选择距离度量是在创建集合时做出的,而正确的选择取决于您使用的数据类型以及向量的创建方式。以下是三种最常见的距离度量:
欧几里得距离: 直线路径。 就像测量空间中两点之间的物理距离一样。当实际距离(如空间数据)重要时,选择这个。
余弦相似度: 这一点是关于角度,而不是长度。它测量两个向量朝同一方向指向的程度,因此在您更关心意义而非大小时,它非常适用于文本或文档。例如,如果两个事物是 相似的,相反的 或 不相关的:

- 点积: 这考察了两个向量的对齐程度。它在推荐系统中非常流行,您需要了解两件事“彼此之间有多一致”。
基于RAM和Memmap的存储
默认情况下,Qdrant 将向量存储在 RAM 中,为适合内存的数据集提供极快的访问速度。但是,当您的数据集超过 RAM 容量时,Qdrant 提供了 Memmap 作为替代方案。
Memmap 允许您将向量 存储在磁盘上,但仍然可以通过直接将数据映射到内存中来高效访问它们,前提是您有足够的 RAM。要启用它,您只需在 创建集合时: 设置 "on_disk": true。
from qdrant_client import QdrantClient, models
client = QdrantClient(url='http://localhost:6333')
client.create_collection(
collection_name="{collection_name}",
vectors_config=models.VectorParams(
size=768, distance=models.Distance.COSINE, on_disk=True
),
)
有关其他配置,如 hnsw_config.on_disk 或 memmap_threshold,请参见 Qdrant 文档中的 存储.
软件开发工具包
Qdrant 提供了一系列的 SDK。您可以使用最熟悉的编程语言,无论您是在编写 Python、去、Rust、Javascript/Typescript、C# 还是 Java。
向量数据库的核心功能

当你想到传统数据库时,这些操作是熟悉的:你创建、读取、更新和删除记录。这些是基础。而且你知道吗?在许多方面,向量数据库的工作方式是相同的,但操作被翻译为向量的复杂性。
1. 索引:HNSW索引和向Qdrant发送数据
为您的向量建立索引就像在传统数据库中创建一个条目。但是对于向量数据库来说,这一步是非常重要的。向量需要以一种易于后续搜索的方式进行索引。
HNSW(分层可导航的小世界)是一种强大的索引算法,大多数向量数据库依赖它来组织向量,以实现快速高效的搜索。
它构建了一个多层图,每个向量是一个节点,连接代表相似性。较高的层连接广泛相似的向量,而较低的层链接关系紧密的向量,使得搜索在深入时逐渐变得更加精细。

当你执行搜索时,HNSW从顶部开始,通过在层之间跳转快速缩小搜索范围。它在深入时只关注相关的向量,随着每一步的推进,优化搜索。
1.1 有效载荷索引
在Qdrant中,索引是模块化的。您可以独立为向量和负载配置索引。负载索引负责基于元数据优化过滤。每个负载索引是为特定字段构建的,允许您根据特定条件快速过滤向量。

您需要为每个字段构建有效负载索引。这里的魔力在于组合:HNSW找到相似的向量,而有效负载索引确保只有符合您标准的向量被筛选出来。了解更多关于Qdrant的可过滤HNSW以及为什么它是这样构建的。
将全文搜索与基于向量的搜索相结合,给您提供了更大的灵活性。您可以在同一个查询中同时搜索概念上相似的文档,同时确保特定的关键词存在。
2. 搜索:近似最近邻(ANN)搜索
相似性搜索允许您按 意义 进行搜索。通过这种方式,您可以进行诸如寻找引起相同情绪的相似歌曲、找到符合您艺术视野的图像,甚至探索文本中的情感模式等搜索。

它的工作方式是,当用户查询数据库时,此查询也会转换为一个向量。算法迅速识别出图形中可能包含与查询向量最接近的向量的区域。

搜索然后逐步向下移动,逐渐缩小到更相关和相关的向量。一旦在底层识别到最接近的向量,这些点就会转回到实际数据中,表示您的 最高得分文档。
这是该过程的概述:

3. 更新向量:实时和批量调整
数据不是静态的,向量也不是。保持向量的最新状态对于维持搜索的相关性至关重要。
向量更新不一定需要立即发生,但当需要时,Qdrant通过简单的API调用高效地处理实时修改:
client.upsert(
collection_name='product_collection',
points=[PointStruct(id=product_id, vector=new_vector, payload=new_payload)]
)
对于大规模更改,例如在模型更新后重新索引向量,批量更新允许您在不影响搜索性能的情况下一次更新多个向量:
batch_of_updates = [
PointStruct(id=product_id_1, vector=updated_vector_1, payload=new_payload_1),
PointStruct(id=product_id_2, vector=updated_vector_2, payload=new_payload_2),
# Add more points...
]
client.upsert(
collection_name='product_collection',
points=batch_of_updates
)
4. 删除向量:管理过时和重复数据
高效的向量管理是保持搜索准确和数据库精简的关键。删除代表过时或不相关数据的向量,例如过期的产品、旧的新闻文章或归档的个人资料,有助于维持性能和相关性。
在Qdrant中,移除向量是简单直接的,只需要指定向量ID:
client.delete(
collection_name='data_collection',
points_selector=[point_id_1, point_id_2]
)
您可以使用删除来移除过时的数据,清理重复项,并通过在设定的时间段后自动删除向量来管理向量的生命周期,以保持您的数据集相关且集中。
密集向量与稀疏向量

现在你了解了什么是向量以及它们是如何创建的,让我们进一步了解你可以使用的两种可能的向量类型:稠密向量或稀疏向量。这两者之间的主要区别是:
1. 稠密向量
稠密向量在字面上是信息稠密的。向量中的每个元素都对数据的语义意义、关系和细微差别做出贡献。该句子的稠密向量表示可能如下所示:

每个数字都有其分量。它们共同传达了句子的整体意思,并且在识别上下文相似的项目时更为有效,即使单词不完全匹配。
2. 稀疏向量
稀疏向量的操作方式不同。它们仅关注于核心内容。在大多数稀疏向量中,许多元素都是零。当一个特征或标记存在时,会被标记——否则为零。
在此图中,您可以看到一句话,“我爱向量相似性,” 通过分词被分解为像 “我,” “爱,” “向量” 的标记。每个标记都被分配一个来自庞大词汇表的唯一 ID。例如,“我” 变为 193,而 “向量” 变为 15012。

稀疏向量用于精确匹配和特定基于令牌的识别。右侧的值,如193: 0.04和9182: 0.12,是每个令牌的分数或权重,显示每个令牌在上下文中的相关性或重要性。最终结果是一个稀疏向量:
{
193: 0.04,
9182: 0.12,
15012: 0.73,
6731: 0.69,
454: 0.21
}
向量空间中的其他一切都假定为零。
稀疏向量非常适合于像 关键词搜索 或 元数据过滤 这样的任务,您需要检查特定标记的存在,而无需捕捉完整的意义或上下文。它们适合于 数据本身 内部的精确匹配,而不是依赖于由有效负载过滤处理的外部元数据。
混合搜索的好处

有时候,仅仅上下文是不够的。有时候你还需要精确度。稠密向量在需要根据数据的上下文或含义检索结果时非常有效。稀疏向量在你需要关键词或特定属性匹配时也很有用。
通过混合搜索,您不必选择其中一个,而是可以同时使用两者,以获得更相关和过滤的搜索结果。
为了实现这种平衡,Qdrant使用归一化和融合技术来融合来自多种搜索方法的结果。一种常见的方法是倒数排名融合 (RRF),将来自不同方法的结果进行合并,给予两个方法都高度排名的项目更高的重要性。这确保了最佳候选者,无论是通过稠密向量还是稀疏向量识别的,都出现在结果的最前面。
Qdrant通过归一化和融合的过程结合了密集和稀疏向量结果。

如何在Qdrant中使用混合搜索
Qdrant 通过其查询 API 使实现混合搜索变得简单。以下是您如何在自己的项目中实现它的方法:

示例混合查询: 假设一个研究人员正在寻找关于自然语言处理的论文,但论文必须在内容中具体提到“transformers”:
search_query = {
"vector": query_vector, # Dense vector for semantic search
"filter": { # Filtering for specific terms
"must": [
{"key": "text", "match": "transformers"} # Exact keyword match in the paper
]
}
}
在这个查询中,致密向量搜索查找与NLP这一广泛主题相关的论文,而稀疏向量过滤确保这些论文特别提到“transformers”。
这只是一个简单的示例,您可以做的事情还有很多。请查看我们的完整混合搜索指南,以了解幕后发生的事情以及构建混合搜索系统时的所有可能性。
量化:获得40倍更快的结果

随着你的向量数据集变得越来越大,搜索它的计算需求也随之增加。
量化向量要小得多,并且更容易比较。使用像 二进制量化 这样的方法,您可以看到 搜索速度提高多达 40 倍,同时内存使用减少 32 倍。在处理大数据集或需要低延迟结果时,这些改进可能会具有决定性意义。
它通过将高维向量转换为二进制表示来工作,通常每个维度使用 4 bytes,每个维度仅使用 1 bit。大于零的值变为“1”,其余的值变为“0”。

量化降低了数据精度,是的,这确实会导致一些准确性的损失。然而,对于二进制量化, OpenAI embeddings 在仅损失 5% 准确率的情况下实现了性能提升。如果你应用像 过采样 和 重评分 这样的技术,这种损失可以进一步降低。
然而,二进制量化并不是唯一可用的选项。像 标量量化 和 积量化 这样的技术在优化向量压缩时也是受欢迎的替代方案。
您可以在创建新集合时使用 quantization_config 参数设置您选择的量化方法:
client.create_collection(
collection_name="{collection_name}",
vectors_config=models.VectorParams(
size=1536,
distance=models.Distance.COSINE
),
# Choose your preferred quantization method
quantization_config=models.BinaryQuantization(
binary=models.BinaryQuantizationConfig(
always_ram=True, # Store the quantized vectors in RAM for faster access
),
),
)
您可以通过将 on_disk=True 设置为在 vectors_config 中将原始向量存储在磁盘上,从而节省 RAM 空间,同时将量化后的向量保留在 RAM 中以便更快访问
我们推荐查看我们的 向量量化指南,获取有关方法和提升 性能优化 的完整解析,以满足您的特定用例。
分布式部署
在考虑扩展时,关键因素包括 容错能力、负载均衡 和 可用性。单个节点,无论多么强大,只能带你走到某个程度。最终,你需要将工作负载分散到多个机器上,以确保系统保持快速和稳定。
分片:在节点之间分配数据
在分布式Qdrant集群中,数据被分割成称为shards的小单位,这些单位分布在不同的节点上。这有助于平衡负载,并确保查询可以并行处理。
每个集合——一个相关数据点的组——可以分成不重叠的子集,这些子集由不同的节点管理。

Raft共识 确保所有节点保持同步并对数据有一致的视图。每个节点都知道每个分片的位置,Raft确保所有节点都是同步的。如果一个节点失败,其他节点知道缺失数据的位置并可以接管。
默认情况下,您Qdrant系统中的分片数量与集群中的节点数量相匹配。但是,如果您需要更多控制,您可以在创建集合时手动选择shard_number。
client.create_collection(
collection_name="{collection_name}",
vectors_config=models.VectorParams(size=300, distance=models.Distance.COSINE),
shard_number=4, # Custom number of shards
)
有两种主要的分片类型:
- 自动分片: 点(向量)通过一致性哈希自动分布到各个分片中。每个分片包含数据的非重叠子集。
- 用户定义分片: 指定点的分布方式,使您能够更好地控制数据的组织,特别是用于 多租户 的情况,其中每个租户(用户、客户或组织)都有他们自己隔离的数据。
每个分片被分为段。它们是分片内的一个更小的存储单元,存储一部分向量及其相关负载(元数据)。当执行查询时,它仅针对相关的段,并并行处理它们。

复制:高可用性和数据完整性
您不想让单点故障导致您的系统瘫痪,对吧?复制保持在不同节点上相同数据的多个副本,以确保 高可用性。
在Qdrant中,副本集管理着不同节点之间这些分片的副本。如果一个副本不可用,其他副本将接管并保持系统运行。数据是本地还是远程主要受您如何配置集群的影响。

当发出查询时,如果相关数据存储在本地,地方分片将处理该操作。如果数据在远程分片,则通过 gRPC 进行检索。
您可以通过 replication_factor 控制您想要的副本数量。例如,创建一个具有4个分片和2的副本因子的集合将导致在集群中分布8个物理分片:
client.create_collection(
collection_name="{collection_name}",
vectors_config=models.VectorParams(size=300, distance=models.Distance.COSINE),
shard_number=4,
replication_factor=2,
)
我们建议同时使用分片和复制,以便将数据分散到各个节点并进行复制以提高可用性。
有关<强>用户定义分片、节点故障恢复和<强>一致性保证等功能的更多细节,请参阅我们的分布式部署指南。
多租户:多租户架构的数据隔离

分片有效地将数据分布在各个节点上,而复制则保证了冗余和容错。但当你有多个客户端或用户组时,如何在同一基础设施内保持他们的数据隔离呢?
多租户允许您在单一集群中将不同租户(用户、客户或组织)的数据隔离。您可以不必为 Tenant 1 和 Tenant 2 创建单独的集合,而是将它们的数据存储在同一个集合中,但用 group_id 标记每个向量以识别它属于哪个租户。

在后端,Qdrant 可以将 Tenant 1 的数据存储在位于加拿大的 Shard 1(可能出于 GDPR 等合规原因),而 Tenant 2 的数据存储在位于德国的 Shard 2。数据将被物理分离,但仍在同一基础设施内。
要实现这一点,您在更新插入操作期间使用租户特定的 group_id 为每个向量打标签:
client.upsert(
collection_name="tenant_data",
points=[models.PointStruct(
id=2,
payload={"group_id": "tenant_1"},
vector=[0.1, 0.9, 0.1]
)],
shard_key_selector="canada"
)
每个租户的数据保持隔离,同时仍然受益于共享基础设施。在优化数据隐私、遵守地方规定和可扩展性的同时,无需为每个租户创建过多的集合或维护单独的集群。
如果你想了解更多关于在Qdrant中使用多租户设置的信息,可以查看我们的 多租户和自定义分片专门指南。
数据安全与访问控制
向量数据库中的一个常见安全风险是嵌入反演攻击的可能性,在这种攻击中,攻击者可能从嵌入中重建原始数据。在将向量数据库投入生产之前,有许多保护层可以用来确保您的实例,这些保护非常重要。
对于简单用例的快速安全性,您可以使用 API 密钥认证。要启用它,请在配置或环境变量中设置 API 密钥。
service:
api_key: your_secret_api_key_here
enable_tls: true # Make sure to enable TLS to protect the API key from being exposed
设置完成后,请记得在所有请求中包含API密钥:
from qdrant_client import QdrantClient
client = QdrantClient(
url="https://localhost:6333",
api_key="your_secret_api_key_here"
)
在更高级的设置中,Qdrant 使用 JWT (JSON Web Tokens) 来执行 基于角色的访问控制 (RBAC)。
RBAC定义了角色并分配权限,而JWT将这些角色安全地编码成令牌。每个请求都根据用户的JWT进行验证,确保他们只能根据分配的权限访问或修改数据。
您可以通过Qdrant Web UI:轻松设置您的访问令牌并安全访问敏感数据。

默认情况下,Qdrant 实例是 不安全的,因此在进入生产环境之前配置安全措施非常重要。要了解有关如何为您的 Qdrant 实例配置安全性和其他高级选项的更多信息,请查看 官方 Qdrant 安全文档。
实验时间
正如我们在本文中看到的,向量数据库绝对不仅仅是我们传统意义上的数据库。它开启了一个可能性世界,从高级相似性搜索到混合搜索,允许在上下文和精确度之间进行内容检索。
但是,没有比实践更好的学习方式。尝试构建一个语义搜索引擎或从零开始实验部署一个混合搜索服务。你会意识到可以利用向量的方式是无穷无尽的。
| 用例 | 工作原理 | 示例 |
|---|---|---|
| 相似性搜索 | 使用向量距离查找相似的数据点 | 查找相似的产品图片,基于主题检索文档,发现相关主题 |
| 异常检测 | 基于向量空间的偏差识别离群值 | 检测银行中的异常用户行为,发现不规则模式 |
| 推荐系统 | 使用向量嵌入来学习和建模用户偏好 | 个性化电影或音乐推荐,电子商务产品建议 |
| RAG(检索增强生成) | 将向量搜索与大型语言模型(LLMs)结合,以提供上下文相关的答案 | 客户支持、自动生成文档摘要、研究报告 |
| 多模态搜索 | 在单个查询中跨不同类型的数据进行搜索,如文本、图像和音频。 | 搜索带有描述和图像的产品,根据音频或文本检索图像 |
| 语音与音频识别 | 使用向量表示来识别和检索音频内容 | 语音转文本转录、语音控制的智能设备、识别和分类声音 |
| 知识图谱增强 | 使用向量将非结构化数据链接到知识图谱中的概念 | 将研究论文链接到相关研究,将客户评价连接到产品特性,将专利按创新趋势进行组织 |
您还可以观看我们的教程视频,开始使用Qdrant从示例数据集中生成语义搜索结果和推荐。
哇!我希望你发现这里的一些概念对你有用。如果你有任何问题,请随时在我们的 Discord社区 中提问,我们的团队将非常乐意帮助你!
记住,不要迷失在向量空间中! 🚀

