Управление оптимизаторами#
Как показала практика гораздо эффективнее применять изменения пакетно, чем выполнять каждое изменение по отдельности. В этом отношении Platform V Vector DB (далее - Vector DB) не является исключением. Поскольку Vector DB работает со структурами данных, которые не всегда легко изменить, иногда необходимо полностью перестроить эти структуры.
Оптимизация хранилища в Vector DB происходит на уровне сегментов (подробнее описано в документе Руководство администратора раздел Настройка хранилища). При этом сегмент, подлежащий оптимизации, остается доступным для чтения во время перестройки.
Доступность достигается путем обертывания сегмента в прокси-сервер, который прозрачно обрабатывает изменения данных. Измененные данные помещаются в сегмент типа copy-on-write, который имеет приоритет при извлечении и последующих обновлениях.
Оптимизатор Vacuum#
Простейшим примером случая, когда требуется перестроить репозиторий сегмента, является удаление точек. Как и многие другие базы данных, Vector DB не удаляет записи сразу после запроса. Вместо этого он помечает записи как удаленные и игнорирует их для будущих запросов.
Данная стратегия позволяет минимизировать доступ к диску — одну из самых медленных операций. Однако побочным эффектом этой стратегии является то, что со временем накапливаются удаленные записи, которые занимают память и замедляют систему.
Чтобы избежать этих неблагоприятных последствий, используется оптимизатор Vacuum. Он применяется, если сегмент накопил слишком много удаленных записей.
Критерии запуска оптимизатора определены в конфигурационном файле.
Например:
storage:
optimizers:
# Минимальная доля удаленных векторов в сегменте, необходимая для выполнения оптимизации сегмента
deleted_threshold: 0.2
# Минимальное количество векторов в сегменте, необходимое для выполнения оптимизации сегмента
vacuum_min_vector_number: 1000
Объединяющий оптимизатор#
Сервис может потребовать создания временных сегментов. Такие сегменты, например, создаются как сегменты типа copy-on-write непосредственно во время самой оптимизации.
Также важно иметь хотя бы один небольшой сегмент, который Vector DB будет использовать для хранения часто обновляемых данных. С другой стороны, слишком большое количество небольших сегментов приводит к неоптимальной производительности поиска.
Объединяющая оптимизация постоянно пытается уменьшить количество сегментов, если их слишком много. Желаемое количество сегментов задается параметром default_segment_number и по умолчанию равно количеству процессоров. Оптимизатор может объединить три наименьших сегмента в один.
Сегменты не будут объединены, если они превысят максимально допустимый размер сегмента, заданный параметром max_segment_size_kb. Это предотвращает создание сегментов, которые слишком велики для эффективного индексирования. Увеличение этого числа может помочь сократить количество сегментов при большом количестве данных и потенциально повысить производительность поиска.
Критерии запуска оптимизатора определяются в конфигурационном файле.
Например:
storage:
optimizers:
# Целевое количество сегментов, которые оптимизатор будет пытаться поддерживать.
# Фактическое количество сегментов может варьироваться в зависимости от нескольких параметров:
# - Количество хранимых точек
# - Текущий уровень записей в секунду (RPS)
#
# Рекомендуется выбирать начальное количество сегментов как кратное количеству потоков поиска,
# чтобы каждый сегмент равномерно обрабатывался одним из потоков.
# Если `default_segment_number = 0`, значение будет автоматически определено на основе количества доступных ядер процессора.
default_segment_number: 0
# Не создавать сегменты больше этого размера (в Килобайтах).
# Большие сегменты могут требовать чрезмерно длительное время индексации,
# поэтому имеет смысл ограничить размер сегментов.
#
# Если приоритет — скорость индексации, установите это значение ниже.
# Если важнее скорость поиска — установите это значение выше.
# Примечание: 1 Кб = 1 вектор размером 256
# Если не задано, будет автоматически определено с учетом количества доступных ядер процессора.
max_segment_size_kb: null
Оптимизатор индексирования#
Vector DB позволяет выбирать тип индексов и методы хранения данных в зависимости от количества записей. Так, например, если количество точек меньше 10000, использование любого индекса было бы менее эффективно, чем полный перебор.
Оптимизатор индексирования используется для реализации включения индексов и метода хранения memmap, когда достигнуто минимальное количество записей.
Критерии запуска оптимизатора указаны в конфигурационном файле.
Например:
storage:
optimizers:
# Максимальный размер (в килобайтах) векторов для хранения в памяти на сегмент.
# Сегменты, превышающие этот порог, будут храниться как файлы с отображением в память (read-only).
# Хранение в memmap-файлах отключено по умолчанию. Чтобы включить его, задайте этому порогу разумное значение.
# Чтобы отключить хранение в memmap-файлах, установите это значение в `0`.
# Примечание: 1 Кб = 1 вектор размером 256
memmap_threshold: 200000
# Максимальный размер (в килобайтах) векторов, разрешенных для обычного индекса,
# превышение этого порога включит векторное индексирование.
# Значение по умолчанию — 20 000, основано на <https://github.com/google-research/google-research/blob/master/scann/docs/algorithms.md>.
# Чтобы отключить векторное индексирование, установите значение `0`.
# Примечание: 1 Кб = 1 вектор размером 256.
indexing_threshold_kb: 20000
Помимо конфигурационного файла, можно отдельно задать параметры оптимизатора для каждой коллекции.
Динамическое обновление параметров может оказаться полезным, например, для более эффективной начальной загрузки точек. Можно отключить индексацию во время процесса загрузки с помощью этих настроек и включить ее сразу после его завершения. В результате на повторное построение индекса не будут тратиться дополнительные вычислительные ресурсы.