每个集合中的数据都被划分成片段。每个片段都有独立的向量存储、有效载荷存储和索引。
片段中的数据通常不会重叠。然而,将同一点存储在不同的片段中不会导致问题,因为搜索包含去重机制。
片段包括向量存储、有效载荷存储、向量索引、有效载荷索引和id映射器,用于存储内部和外部id之间的关系。
片段可以是“可追加”的或“不可追加”的,这取决于所使用的存储和索引类型。您可以在“可追加”片段中自由地添加、删除和查询数据。而“不可追加”片段只能读取和删除数据。
集合中片段的配置可以是不同的,且彼此独立,但至少需要一个“可追加”片段。
向量存储
根据应用程序的需求,Qdrant可以使用以下其中一种数据存储选项。选择必须在搜索速度和使用RAM的大小之间进行权衡。
内存存储 - 将所有向量存储在RAM中,具有最高的速度,因为只有在持久化时才需要磁盘访问。
Memmap存储 - 在磁盘上创建与文件相关联的虚拟地址空间。Mmapped文件不直接加载到RAM中,而是使用页面缓存来访问文件内容。这种方案允许灵活使用可用内存。具有足够的RAM,它的速度几乎和内存存储一样快。
配置Memmap存储
有两种方式来配置使用memmap(也称为在磁盘上存储):
- 在集合创建API中为向量设置
on_disk
选项:
仅适用于 v1.2.0 及更高版本
PUT /collections/{collection_name}
{
"vectors": {
"size": 768,
"distance": "Cosine",
"on_disk": true
}
}
这将创建一个立即将所有向量存储在memmap存储中的集合。在Qdrant实例使用快速磁盘并且需要处理大型集合时,这是推荐的方式。
- 设置
memmap_threshold_kb
选项。此选项将设置将片段转换为memmap存储的阈值。
有两种方式实现:
- 可以在配置文件中全局设置阈值。参数名为
memmap_threshold_kb
。 - 可以在集合创建或更新期间为每个集合单独设置阈值。
PUT /collections/{collection_name}
{
"vectors": {
"size": 768,
"distance": "Cosine"
},
"optimizers_config": {
"memmap_threshold": 20000
}
}
设置memmap阈值参数的经验法则很简单:
- 如果使用场景均衡 - 将memmap阈值设置为与
indexing_threshold
相同(默认为20000)。在这种情况下,优化器不会进行任何额外的运行,并且将一次性优化所有阈值。 - 如果写入负载很高,RAM很低 - 将memmap阈值设置为比
indexing_threshold
更低,例如10000。在这种情况下,优化器将首先将片段转换为memmap存储,然后再应用索引。
另外,您不仅可以将memmap存储用于向量,还可以将其用于HNSW索引。要启用此功能,您需要在创建集合时将hnsw_config.on_disk
参数设置为true
。
PUT /collections/{collection_name}
{
"vectors": {
"size": 768,
"distance": "Cosine"
},
"optimizers_config": {
"memmap_threshold": 20000
},
"hnsw_config": {
"on_disk": true
}
}
负载(payload)存储
Qdrant 支持两种类型的负载存储:InMemory(内存存储)和 OnDisk(磁盘存储)。
InMemory 负载存储与内存向量相同的方式进行组织。负载数据在服务启动时加载到内存中,而磁盘和RocksDB仅用于持久化。这种类型的存储速度非常快,但是可能需要大量的内存空间来存储所有数据,特别是如果负载附加了大型值(如文本摘要甚至图像)。
对于大型负载值,最好使用 OnDisk 负载存储。这种类型的存储将直接将负载读写到 RocksDB,因此不需要大量的内存来存储。然而,缺点是访问延迟。如果您需要查询基于负载的条件的向量-检查存储在磁盘上的值可能需要太长时间。在这种情况下,我们建议为每个用于过滤条件的字段创建负载索引,以避免磁盘访问。一旦创建了字段索引,Qdrant 将始终将索引字段的所有值保存在内存中,而不管负载存储类型如何。
您可以通过配置文件或在创建集合时使用 collection 参数 on_disk_payload
来指定所需的负载存储类型。
版本控制
为了确保数据的完整性,Qdrant 在两个阶段进行所有数据更改。首先,数据被写入 Write-ahead-log(WAL)中,WAL 对所有操作进行排序并分配顺序编号。
一旦更改被添加到 WAL 中,即使发生断电,也不会丢失。然后,更改进入段中。每个段存储应用于其的最新版本的更改,以及每个单独点的版本。如果新更改的顺序编号小于点的当前版本,则更新器将忽略该更改。这个机制允许 Qdrant 在异常关闭的情况下安全高效地从 WAL 恢复存储。