Каждая коллекция данных разделена на сегменты. У каждого сегмента есть независимое векторное хранилище, хранилище полезной нагрузки и индекс.
Данные в сегментах обычно не пересекаются. Однако сохранение одной и той же точки в разных сегментах не вызывает проблем, поскольку поиск содержит механизм дедупликации.
Сегменты включают в себя векторное хранилище, хранилище полезной нагрузки, векторный индекс, индекс полезной нагрузки и отображение идентификаторов для хранения связи между внутренними и внешними идентификаторами.
Сегменты могут быть "добавляемыми" или "недобавляемыми" в зависимости от типа используемого хранилища и индекса. Вы можете свободно добавлять, удалять и запрашивать данные в "добавляемых" сегментах, в то время как в "недобавляемых" сегментах можно только читать и удалять данные.
Конфигурация сегментов в коллекции может быть разной и независимой друг от друга, но по крайней мере один сегмент должен быть "добавляемым".
Векторное хранилище
В зависимости от потребностей приложения Qdrant может использовать один из следующих вариантов хранения данных. Выбор должен сбалансировать скорость поиска и использование оперативной памяти.
Хранилище в памяти - Сохраняет все векторы в оперативной памяти, обеспечивая высочайшую скорость, так как доступ к диску требуется только во время сохранения.
Хранилище с отображением в память (memmap) - Создает виртуальное адресное пространство, связанное с файлом на диске. Отображаемые файлы не загружаются напрямую в оперативную память, а доступ к ним осуществляется с помощью кэширования страниц. Этот подход позволяет гибко использовать доступную память. При достаточном объеме оперативной памяти его скорость почти такая же быстрая, как у хранилища в памяти.
Настройка хранилища с отображением в память (memmap)
Есть два способа настроить использование отображения в память (также известного как хранение на диске):
- Установите параметр
on_disk
для векторов в API создания коллекции:
Применяется только к версии v1.2.0 и выше
PUT /collections/{collection_name}
{
"vectors": {
"size": 768,
"distance": "Cosine",
"on_disk": true
}
}
Это создаст коллекцию, которая немедленно сохраняет все векторы в хранилище с отображением в память. Это рекомендуемый подход, когда экземпляр Qdrant использует быстрые диски и нужно обрабатывать большие коллекции.
- Установите параметр
memmap_threshold_kb
. Этот параметр устанавливает порог для преобразования сегментов в хранилище с отображением в память.
Есть два способа реализации этого:
- Установите порог глобально в файле конфигурации. Имя параметра -
memmap_threshold_kb
. - Установите порог индивидуально для каждой коллекции при создании или обновлении.
PUT /collections/{collection_name}
{
"vectors": {
"size": 768,
"distance": "Cosine"
},
"optimizers_config": {
"memmap_threshold": 20000
}
}
Правило установки параметра порога memmap простое:
- Если сценарий использования сбалансирован - установите порог memmap таким же, как у
indexing_threshold
(по умолчанию 20000). В этом случае оптимизатор не выполнит никаких дополнительных запусков и оптимизирует все пороговые значения сразу. - Если нагрузка на запись высока, а оперативной памяти мало - установите порог memmap ниже, чем у
indexing_threshold
, например 10000. В этом случае оптимизатор сначала преобразует сегменты в хранилище с отображением в память, а затем выполнит индексацию.
Кроме того, отображаемое хранилище можно использовать не только для векторов, но также для индексов 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
}
}
Хранение данных
Qdrant поддерживает два типа хранения данных: InMemory и OnDisk.
Хранение данных InMemory организует данные payload таким же образом, как и вектора в памяти. Данные payload загружаются в память при запуске сервиса, в то время как на диске и RocksDB используются только для постоянного хранения. Этот тип хранения очень быстр, но может потребовать большого объема памяти для хранения всех данных, особенно если payload включает в себя большие значения (такие как текстовые сводки или даже изображения).
Для больших значений payload предпочтительно использовать хранение данных OnDisk. Этот тип хранения напрямую считывает и записывает payload в RocksDB, тем самым не требуя большого объема памяти для хранения. Однако, есть недостаток в виде задержки доступа. Если вам необходимо запросить векторы на основе условий payload, проверка значений, хранящихся на диске, может занять слишком много времени. В этом случае мы рекомендуем создать индекс payload для каждого поля, используемого для фильтрационных условий, чтобы избежать доступа к диску. После создания индекса поля Qdrant всегда будет держать все значения индексированного поля в памяти, независимо от типа хранения payload.
Вы можете указать желаемый тип хранения payload через файл конфигурации или используя параметр коллекции on_disk_payload
при создании коллекции.
Контроль версий
Для обеспечения целостности данных Qdrant выполняет все изменения данных в двух этапах. Сначала данные записываются в журнал транзакций (WAL), который сортирует и присваивает последовательные номера всем операциям.
Как только изменения добавлены в WAL, они не теряются даже в случае сбоя питания. Затем изменения попадают в сегмент. Каждый сегмент хранит последнюю версию примененных к нему изменений, а также версию каждой отдельной точки. Если последовательный номер нового изменения меньше текущей версии точки, обновление будет игнорироваться. Этот механизм позволяет Qdrant эффективно восстанавливать хранение данных из WAL в случае аварийного выключения.