Внешняя коллекция Milvus: индексация и поиск данных в озере данных без их перемещения
Во многих конвейерах ИИ эмбеддинги и метаданные уже создаются и хранятся в озере данных. Продуктовый конвейер может записывать атрибуты продуктов и мультимодальные эмбеддинги в файлы Parquet в S3. Корпус для поиска или обучения может жить в таблице Iceberg или Lance. Озеро уже является тем местом, где эти наборы данных генерируются, обновляются, версионируются и используются остальной частью стека данных.
Векторные базы данных, однако, традиционно строились вокруг обслуживающей копии, принадлежащей базе данных. Если командам нужен был низколатентный векторный поиск по данным, уже находящимся в озере, у них обычно было два варианта:
- Скопировать данные в векторную базу данных. Это обеспечивает ANN-индексы и производственный путь обслуживания, но создает вторую копию набора данных и ETL-пайплайн, который должен оставаться синхронизированным с источником.
- Запрашивать озеро напрямую. Это позволяет избежать дублирования, но без слоя ANN-индексирования и обслуживания векторный поиск откатывается к сканированиям, не предназначенным для производственной задержки.
Milvus 3.0 Внешняя коллекция предлагает третий путь. Исходные данные остаются в Parquet, Iceberg, Lance, Vortex или другом поддерживаемом внешнем формате, а Milvus строит и обслуживает индексы на них. Вы сопоставляете внешние поля со схемой Milvus, определяете необходимые индексы, выполняете Refresh коллекции и используете обычные API поиска и запросов Milvus — без предварительного копирования исходных строк в управляемую коллекцию Milvus.
Архитектурное изменение простое: данные могут оставаться в озере, а Milvus добавляет слой индексирования и поиска.
Это также делает Внешнюю коллекцию важным шагом к Vector Lakebase, единой lake-нативной архитектуре данных для ИИ, которая сочетает обслуживание уровня векторной базы данных с открытым хранением в озере, переиспользуемыми индексами уровня озера и общим семантическим слоем. Онлайн-поиск больше не должен исходить из отдельной обслуживающей копии, пока Spark, пайплайны обучения, задачи оценки и инструменты управления работают с другой версией данных. Они могут работать на одной и той же основе данных, размещенных в озере.
Что такое Внешняя коллекция и что она меняет
Внешняя коллекция — это тип коллекции Milvus, исходные данные которой находятся вне управляемого Milvus хранилища.
Без Внешней коллекции размещение этого каталога за производственным векторным поиском обычно означает создание еще одной копии в Milvus:
Каждый раз, когда каталог меняется, меняется модель эмбеддингов или выполняется обратная заливка поля, очередной пайплайн должен переносить обновленные данные через эту границу.
С Внешней коллекцией архитектура становится следующей:
Milvus не делает внешние файлы собственной копией исходных данных. Вместо этого Внешняя коллекция содержит информацию, необходимую Milvus для их интерпретации и поиска по ним:
external_source, который идентифицирует внешние файлы или таблицу.external_spec, описывающий формат источника и доступ к хранилищу.- Сопоставления
external_field, которые связывают поля в схеме Milvus с колонками во внешнем наборе данных. - Индексы, манифесты и обслуживающее состояние, которые Milvus создает для поиска.
Отсутствие копирования исходных данных не означает отсутствие состояния внутри Milvus. Milvus по-прежнему строит индексы. Он по-прежнему использует вычислительные ресурсы. Он по-прежнему кэширует данные. Изменение заключается в том, что эталонные строки больше не нужно копировать в Milvus только потому, что вам нужен поиск по ним через Milvus.
Обычная коллекция Milvus против Внешней коллекции
| Аспект | Управляемая коллекция Milvus | Внешняя коллекция |
|---|---|---|
| Исходные записи | Хранятся и управляются Milvus | Остаются во внешних файлах или таблице |
| Как данные попадают в Milvus | Вставка, upsert, импорт или потоковая запись | Сопоставление внешнего источника + Refresh |
| Онлайн-мутации | Поддерживаются | Только чтение со стороны Milvus |
| Свежесть | Следует пути записи и модели согласованности Milvus | Следует последнему успешно опубликованному Refresh |
| Состояние, управляемое Milvus | Исходные данные, метаданные, индексы, кэши | Сопоставления, манифесты, индексы, кэши |
| Путь запросов | API поиска и запросов Milvus | API поиска и запросов Milvus |
| Наилучшее применение | Непрерывно меняющиеся онлайн-данные | Большие, создаваемые пакетно, данные озера с высокой долей чтения |
Таким образом, Внешняя коллекция дополняет обычные коллекции Milvus, а не заменяет их.
Система может хранить быстро меняющееся онлайн-состояние в обычных коллекциях Milvus, используя Внешние коллекции для больших корпусов, каталогов, исторических наборов данных, признаков моделей или других данных, уже созданных и управляемых в озере.
Почему удаление второй копии имеет значение
Внешние коллекции легко описать как оптимизацию хранилища: не копируйте несколько терабайт данных в другую базу данных — и вы сэкономите хранилище. Это полезно, но это не главная архитектурная проблема.
Более высокая стоимость возникает из-за необходимости поддерживать согласованность двух систем данных.
Вернемся к каталогу продуктов. Платформа данных создает эталонный набор данных Parquet. Поиск импортирует его в векторную базу данных. Команда рекомендаций может читать те же данные озера через Spark для офлайн-анализа. Затем новая модель эмбеддингов генерирует заменяющий векторный столбец. Запасы и метаданные продолжают меняться одновременно.
Как только онлайн-копия для обслуживания становится независимой от озера, каждое изменение должно пересекать эту границу:
- данные необходимо копировать;
- передачу необходимо планировать и контролировать;
- для упавших заданий нужны повторные попытки;
- схемы и права доступа, возможно, придется представлять в нескольких системах;
- свежесть зависит от того, как быстро синхронизирующий пайплайн догоняет изменения;
- команды должны знать, какая копия представляет ту версию, которая им нужна.
Хранилище — лишь одна статья расходов.
| Стоимость | Отдельная копия озера + обслуживающая копия | Внешняя коллекция |
|---|---|---|
| Копии исходных данных | Копия озера плюс отдельная обслуживающая копия | Исходные строки остаются в озере |
| Перемещение данных | Постоянный ETL/импортный пайплайн | Refresh по внешнему источнику |
| Свежесть | Зависит от ритма экспорта/импорта | Управляется моментом публикации нового Refresh |
| Управление данными | Исходная и обслуживающая копии должны оставаться согласованными | Владение источником, происхождение и версионирование остаются на платформе озера данных |
| Офлайн-переиспользование | Другие потребители могут создавать собственные копии | Существующие инструменты озера могут продолжать читать тот же источник |
| Ресурсы обслуживания | Рассчитываются под копию базы данных и нагрузку запросов | Индексирование, вычислительные ресурсы запросов и кэши могут управляться отдельно от владения исходными строками |
Это различие становится особенно важным по мере того, как данные ИИ меняются все чаще.
Команды дедуплицируют корпусы. Они кластеризуют данные для анализа. Они генерируют новые эмбеддинги при изменении модели. Они добавляют метки, резюме, извлеченные сущности, оценки качества или сигналы обратной связи. Они запускают задачи оценки и пайплайны очистки данных на том же корпусе, из которого производственные приложения выполняют поиск.
Если каждая система владеет собственной копией, каждое улучшение превращается в еще одну задачу синхронизации.
Внешняя коллекция меняет эту границу: офлайн-системы могут продолжать работать с набором данных в озере, в то время как Milvus обслуживает поиск на той же основе.
Какие источники данных поддерживает Внешняя коллекция
Внешняя коллекция спроектирована вокруг открытых, внешне управляемых данных, а не специфичной для Milvus структуры источника. Она поддерживает несколько форматов внешних источников через Storage V3:
| Внешний формат | значение format | Что читает Milvus |
|---|---|---|
| Apache Parquet | parquet | Каталог или префикс объектного хранилища, содержащий файлы Parquet и группы строк |
| Vortex | vortex | Файлы Vortex и их метаданные компоновки |
| Lance | lance-table | Набор данных Lance и его метаданные фрагментов |
| Apache Iceberg | iceberg-table | Метаданные Iceberg плюс выбранный снапшот |
| Milvus snapshot | milvus-table | Поддерживаемый снапшот Milvus, представленный как внешний источник |
Сопоставление между источником и Milvus является явным.
Столбец источника с именем product_id может стать полем Milvus id; image_vec может стать embedding; и широкая исходная таблица не обязана открывать каждый столбец для коллекции. Это значит, что платформе данных не нужно переименовывать или переписывать свой источник только для того, чтобы удовлетворить обслуживающую базу данных.
Версионируемые форматы добавляют еще одно полезное свойство. С таким источником, как Iceberg, коллекция может указывать на конкретный снапшот, а не на то, что актуально на момент выполнения запроса. Фиксированная версия источника полезна для воспроизводимой оценки, регрессионного тестирования, исторического анализа и аудиторских задач.
Базовые файлы также остаются доступными для остальной части стека данных. Spark, фреймворки обучения, системы управления данными и другие совместимые с озером инструменты могут продолжать читать те же открытые данные.
Внешняя коллекция добавляет еще одного потребителя этих данных; она не превращает Milvus в единственного владельца.
Безопасный доступ к внешнему хранилищу
Milvus также требуется разрешение на чтение внешнего хранилища.
В зависимости от провайдера хранилища развертывания могут использовать такие механизмы, как идентификатор рабочей нагрузки или экземпляра, принятие роли AWS STS, имперсонацию сервисного аккаунта, доступ на основе SAS или собственные ролевые системы провайдера, вместо встраивания долгоживущих учетных данных в конфигурацию приложения.
Эта идентичность хранилища определяет, как Milvus получает доступ к источнику. Авторизация внутри Milvus остается отдельной границей безопасности.
Как создать, индексировать, обновлять и запрашивать внешнюю коллекцию
Жизненный цикл Внешней коллекции состоит из четырех основных шагов:
- Определите внешний источник и сопоставьте его столбцы со схемой Milvus.
- Определите индексы, необходимые для рабочей нагрузки.
- Запустите Refresh, чтобы Milvus обнаружил исходные данные и подготовил версию, доступную для запросов.
- Загрузите коллекцию и используйте обычные API поиска и запросов Milvus.
Вот тот же каталог продуктов, представленный в виде Внешней коллекции:
import json
import time
from pymilvus import DataType, MilvusClient
client = MilvusClient(
uri=“http://localhost:19530”,
token=“root:Milvus”,
)
schema = client.create_schema(
external_source=“s3://my-lake/datasets/products/”,
external_spec=json.dumps(
{
“format”: “parquet”,
“extfs”: {
“cloud_provider”: “aws”,
“region”: “us-east-1”,
“use_iam”: “true”,
“iam_endpoint”: “https://sts.us-east-1.amazonaws.com”,
},
}
),
)
schema.add_field(
field_name=“id”,
datatype=DataType.INT64,
external_field=“product_id”,
)
schema.add_field(
field_name=“embedding”,
datatype=DataType.FLOAT_VECTOR,
dim=768,
external_field=“image_vec”,
)
schema.add_field(
field_name=“title”,
datatype=DataType.VARCHAR,
max_length=256,
external_field=“product_name”,
)
schema.add_field(
field_name=“stock”,
datatype=DataType.INT64,
external_field=“stock”,
)
schema.add_field(
field_name=“rating”,
datatype=DataType.FLOAT,
external_field=“rating”,
)
client.create_collection(
collection_name=“products_ext”,
schema=schema,
)
Индексы используют обычный интерфейс Milvus:
index_params = client.prepare_index_params()
index_params.add_index(
field_name="embedding",
index_type="HNSW",
metric_type="COSINE",
)
index_params.add_index(field_name="stock", index_type="AUTOINDEX")
index_params.add_index(field_name="rating", index_type="AUTOINDEX")
client.create_index(
collection_name=“products_ext”,
index_params=index_params,
)
Затем обновите внешний источник:
job_id = client.refresh_external_collection(
collection_name="products_ext",
)
while True:
progress = client.get_refresh_external_collection_progress(job_id=job_id)
if progress.state == “RefreshCompleted”:
break
if progress.state == “RefreshFailed”:
raise RuntimeError(progress.reason)
time.sleep(2)
Когда обновленная версия готова, загрузите и выполните поиск по ней, как по обычной коллекции Milvus:
client.load_collection("products_ext")
results = client.search(
collection_name=“products_ext”,
data=[query_vec],
anns_field=“embedding”,
filter=“stock > 0 and rating >= 4.0”,
limit=10,
output_fields=[“id”, “title”, “stock”, “rating”],
)
Важное отличие заключается не в поисковом вызове. Оно в том, где начинается жизненный цикл. Управляемая коллекция Milvus начинается с записи или импорта данных в Milvus. Внешняя коллекция начинается со ссылки на данные, которые уже существуют в другом месте.
Как Refresh подхватывает изменения во внешних данных
Внешняя коллекция доступна только для чтения со стороны Milvus, но базовый набор данных в озере не должен оставаться замороженным навсегда.
Предположим, продуктовый пайплайн добавляет очередной батч, обновляет метаданные или записывает эмбеддинги из новой модели. Milvus не отслеживает непрерывно каждый объект, появляющийся в пути источника. Эти изменения становятся видимыми через Refresh.
Refresh читает внешние метаданные, разрешает фрагменты источника, обновляет манифесты, связывающие их с коллекцией Milvus, и подготавливает соответствующее состояние индексов.
Ключевой момент в том, что эта работа может быть инкрементальной.
Milvus определяет фрагменты источника, которые не изменились, и может переиспользовать существующую работу по сегментам и индексам. Новые или измененные фрагменты — это те части, которые требуют новой обработки.
Поэтому небольшое изменение в многотерабайтном наборе данных не должно вызывать еще один полный импорт и полное перестроение индекса.
Refresh также дает обслуживающей системе четкую границу версий. Пока подготавливается новая версия, запросы продолжают использовать ранее опубликованное состояние. После завершения Refresh новое состояние становится доступным как полная версия, а не как смесь старых и частично подготовленных данных.
Эта модель естественно подходит для ежечасных сборок каталога, ночных обновлений базы знаний, периодических обновлений эмбеддингов, пайплайнов признаков, генерируемых моделями, и аналогичных пакетных рабочих нагрузок.
Она не заменяет потоковый путь записи. Если каждая вставка или удаление должны немедленно становиться доступными для поиска через Milvus, управляемая коллекция остается лучшей моделью.
Как Lazy Loading снижает использование памяти для широких наборов данных
Хранение исходных строк в объектном хранилище помогает только в том случае, если обслуживающий слой не должен загружать каждый байт локально, прежде чем сможет отвечать на запросы. С включенным многоуровневым хранилищем Milvus это не требуется.
При загрузке коллекции QueryNodes изначально могут хранить только легковесные метаданные, такие как информация о схеме, определения индексов, карты чанков и ссылки на удаленные объекты. Данные полей подтягиваются на уровне чанков, когда они нужны запросу; индексы могут оставаться удаленными до первого использования, а затем кэшироваться локально. Часто используемые данные остаются горячими, а реже запрашиваемые данные могут вытесняться.
Это особенно полезно для широких наборов данных ИИ.
Строка продукта может содержать несколько эмбеддингов, длинное описание, сырой JSON, метаданные изображений, сгенерированные резюме, запасы, цены, рейтинги и множество других атрибутов. Типичный поиск по сходству может затрагивать только один вектор плюс запасы, цену и рейтинг. Нет причин, по которым каждое другое поле должно постоянно занимать память обслуживания только потому, что принадлежит той же записи.
Внешняя коллекция может сузить объем обслуживания на двух уровнях:
- Во-первых, проекция на уровне схемы. С помощью
external_fieldВнешняя коллекция может открывать только те столбцы источника, которые нужны приложению. Остальные столбцы остаются в наборе данных озера и не включаются в эту обслуживающую схему. - Во-вторых, проекция во время выполнения. В многоуровневой модели обслуживания QueryNodes подтягивают и кэшируют поля и индексы, реально необходимые рабочей нагрузке, а не загружают весь сопоставленный набор данных заранее.
Другими словами, набор данных может оставаться широким в озере, не вынуждая объем обслуживания быть таким же широким.
Здесь есть очевидный компромисс. Запрос, обращающийся к холодному полю или индексу, может заплатить за удаленное чтение при первом доступе. Политики прогрева могут предварительно загружать критичные к задержке поля или индексы, а политики кэширования и вытеснения не позволяют реже используемым состояниям бесконечно занимать локальные ресурсы.
Дело не в том, что объектное хранилище ведет себя как оперативная память. Дело в том, что память и локальный диск могут следовать за рабочим набором поисковой нагрузки, а не за общим размером и шириной исходного набора данных.
Формат источника также важен здесь. Форматы, предназначенные для широких аналитических сканирований, и форматы, оптимизированные для более узких или случайных чтений, могут демонстрировать разное поведение ввода-вывода при доступе по требованию. Внешняя коллекция не стирает эти компромиссы на уровне хранилища; она позволяет Milvus построить поверх них слой поиска.
Какие возможности поиска и индексирования поддерживает Внешняя коллекция
Внешняя коллекция не просто указывает Milvus на каталог эмбеддингов и не сканирует файлы. Milvus строит структуры поиска на внешних данных и выполняет запросы через свой стандартный поисковый движок.
Индексы Milvus, построенные на внешних данных
В зависимости от полей и рабочей нагрузки Milvus может строить:
- векторные индексы для ANN-поиска;
- скалярные индексы для фильтрации по метаданным;
- JSON-индексы для полуструктурированных атрибутов;
- индексы BM25 и полнотекстовые индексы для лексического поиска.
- Функционально генерируемые поля, поддерживаемые моделью данных Milvus.
ANN-поиск использует эти индексы, чтобы сузить множество кандидатов, а не читать каждый исходный вектор.
Это различие важно, потому что хранение эмбеддинга в озере — это не то же самое, что работа векторной базы данных поверх него. Персистентность дает вам байты. Производственный поиск также требует индексов, планирования запросов, фильтрации, ранжирования, кэширования и низколатентного пути обслуживания.
За пределами векторного top-K
Еще одна распространенная ошибка — читать «Внешнюю коллекцию» как «векторный поиск по Parquet». Это преуменьшает то, что на самом деле требуется для производственного поиска.
Результат производственного поиска редко зависит только от векторного сходства. Он также может зависеть от точных терминов, политики доступа, наличия на складе, временной метки, категории, цены, качества источника или сигналов бизнес-ранжирования.
Рассмотрим запрос, например:
| красное цветочное платье на лето, в наличии, сначала с самым высоким рейтингом |
|---|
Производственному пути поиска могут потребоваться несколько сигналов:
- Векторное сходство для семантического значения фразы «летнее цветочное платье».
- Лексический или полнотекстовый поиск по точному термину, например «красное».
- Скалярные фильтры, чтобы исключить товары, которых нет в наличии или чей рейтинг ниже порога.
- Гибридный поиск и ранжирование для объединения нескольких поисковых сигналов.
Milvus 3.0 также расширяет механизм запросов за пределы первоначального поиска ближайших соседей такими возможностями, как серверная сортировка, агрегация и фасетирование.
Более широкая мысль состоит в том, что Внешняя коллекция дает данным, размещенным в озере, путь к поиску уровня базы данных — а не просто способ чтения векторов из файлов.
Как одни и те же данные озера поддерживают онлайн-обслуживание и офлайн-обработку
Самая сильная архитектурная причина хранить источник в открытом формате озера не просто в том, что вторая копия стоит денег. Она в том, что один и тот же набор данных может оставаться доступным системам, которые постоянно его улучшают.
Вернемся к каталогу продуктов.
В течение дня Milvus может обслуживать Внешнюю коллекцию для поиска товаров, рекомендаций или поиска для агентов.
В то же время другие системы могут работать напрямую с набором данных в озере:
- Spark может выявлять дублирующиеся товары.
- Пайплайн обучения может генерировать эмбеддинги из новой модели.
- Задача контроля качества данных может обнаруживать некорректные или аномальные записи.
- Оценочный пайплайн может сравнивать качество поиска между версиями моделей.
- Пакетный процесс может генерировать резюме, метки или дополнительные метаданные.
Внешняя коллекция не запускает эти задачи сама. Spark остается Spark; обучение остается обучением. Ее роль — убрать лишнюю границу между обслуживанием и данными.
Офлайн-работа может записывать улучшенные данные или новые поля обратно в озеро. Последующий Refresh делает обновленный источник доступным для поискового пути Milvus.
Больше нет отдельного цикла экспорта и импорта, единственная цель которого — воссоздать еще одну эталонную копию для обслуживания.
Управление данными также остается четко разделенным. Версии источника, происхождение и владение источником остаются на платформе озера данных. Milvus поддерживает собственную авторизацию на уровне коллекции и учетные данные, необходимые для чтения источника. Совместное использование единой основы данных не означает сведение всех доменов безопасности в одну систему.
В этом связь с Vector Lakebase: озеро остается общей основой данных, а Milvus предоставляет низколатентный слой поиска поверх него. Внешняя коллекция — одна из частей этой архитектуры, наряду с Storage V3, снапшотами, интеграцией со Spark, эволюцией схем и обратной заливкой.
Где Внешняя коллекция уместна — а где нет
Внешняя коллекция отлично подходит, когда:
- Ваши эталонные данные уже находятся в Parquet, Vortex, Lance, Iceberg или другом поддерживаемом внешнем источнике.
- Набор данных создается в основном пакетами, а не через высокочастотные транзакционные записи.
- Поддержание второй обслуживающей копии создает значительные накладные расходы на ETL, свежесть или управление данными.
- Нескольким системам нужно работать с одним и тем же открытым набором данных.
- Явная граница Refresh приемлема для свежести обслуживания.
- Вы хотите производственный поиск Milvus, не делая Milvus владельцем исходных строк.
Обычная коллекция Milvus по-прежнему лучший выбор, когда:
- приложение непрерывно вставляет или обновляет записи (upsert);
- удаления должны становиться видимыми через онлайн-путь записи;
- рабочая нагрузка зависит от возможностей коллекции, недоступных для внешних схем;
- Архитектура обслуживания намеренно держит все необходимые данные в памяти, избегая промахов удаленного кэша.
Стоит помнить о нескольких границах.
- Внешние коллекции доступны только для чтения. Изменения источника происходят вне Milvus.
- Отсутствие копирования относится к исходным строкам. Индексы, манифесты, кэши и вычислительные ресурсы по-прежнему требуют затрат.
- Refresh выполняется явно. Это не механизм потоковой синхронизации.
- Источник должен оставаться доступным. Поведение поиска, индексирования и обновления по-прежнему зависит от доступа к хранилищу и учетных данных.
- Требуется Storage V3. В open-source Milvus 3.0 его необходимо включить перед использованием Внешней коллекции.
- Внешняя коллекция не заменяет вышестоящую обработку. Генерация эмбеддингов, кластеризация, дедупликация и очистка данных по-прежнему выполняются в соответствующих вышестоящих системах.
Поэтому выбор здесь взаимодополняющий, а не бинарный. Система может использовать обычные коллекции Milvus для быстро меняющегося онлайн-состояния и Внешние коллекции для больших, создаваемых пакетами наборов данных, естественное место которых — озеро.
Попробуйте Внешнюю коллекцию в Milvus 3.0
Внешняя коллекция доступна в Milvus 3.0. Начните с репрезентативного набора данных в озере и оцените аспекты, важные для вашей рабочей нагрузки: начальное и инкрементальное обновление, стоимость построения индексов, поведение горячих и холодных запросов, а также интервал свежести, необходимый вашему приложению.
Подробности реализации см. в:
Если вы предпочитаете управляемый путь, Внешняя коллекция также доступна как часть Zilliz Vector Lakebase в Zilliz Cloud. См.:
- Внешняя коллекция в Zilliz Cloud
- От векторной базы данных к Vector Lakebase
- Почему мы создали Vector Lakebase: переосмысление архитектуры неструктурированных данных для ИИ
Вы также можете направлять вопросы по реализации и отзывы в репозиторий Milvus на GitHub или в сообщество Milvus в Discord.
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word



