Pesquisa de vetores

Pesquisa ANN filtrada com índices vetoriais compostos (Parte 2)

Esta é a segunda postagem do blog de uma série de várias partes que explora a indexação de vetor composto no Couchbase. Confira a primeira postagem aqui

A série abrangerá:

  1. Por que os índices vetoriais compostos são importantes, incluindo conceitos, terminologia e motivação do desenvolvedor. Um sistema inteligente de recomendação de compras será usado como exemplo.
  2. Como os índices de vetor composto são implementados no Serviço de Indexação do Couchbase.
  3. Como o pushdown ORDER BY funciona para consultas de vetor composto.
  4. Comportamento de desempenho no mundo real e resultados de benchmarking.

Implementação de índices de vetores compostos

O GSI usa a fábrica de índices FAISS. Uma string de índice como a mostrada abaixo será construída a partir do campo de descrição fornecido na DDL.

Exemplo: Com uma string de descrição como “IVF10000,PQ32x8”, será construída uma string de fábrica de índice FAISS como “IVF10000_HNSW,PQ32x8”.

No entanto, essa string de fábrica é usada apenas como um bloco de construção durante o treinamento e a configuração do índice. O GSI não depende do FAISS como um índice monolítico na memória para todo o conjunto de dados. Em vez disso, o FAISS é aplicado seletivamente em dados amostrados para aprender centroides e livros de códigos de quantização, enquanto o layout completo do índice, o armazenamento, o tratamento de mutação e a execução de consultas são gerenciados pelo Couchbase. Isso permite que o Couchbase dimensione a pesquisa vetorial de forma eficiente, integre a filtragem escalar e a semântica de consulta e ofereça suporte a atualizações contínuas - que vão muito além da invocação de um índice FAISS autônomo.

Embeddings

A camada de incorporação pega os campos de texto relevantes, envia-os por meio de um modelo de transformação e produz vetores semânticos que representam cada produto. Esses vetores alimentam a pesquisa ANN. O aplicativo deve armazenar essas incorporações junto com os dados do produto para que o índice vetorial possa usá-las e garantir que as incorporações armazenadas correspondam à definição do índice vetorial (por exemplo, dimensão fixa e tipo numérico) esperada pelo Couchbase.

Criação e desenvolvimento de índices

Criar e desenvolver o fluxo

  • Como o usuário tem um número suficiente de vetores armazenados, o GSI faz uma amostragem aleatória dos dados para criar um conjunto de dados representativo.
  • Esse conjunto de dados representativo é usado para treinar o índice FAISS. Após o treinamento, o GSI mantém o livro de códigos que inclui uma lista invertida IVF e livros de códigos PQ:
    • O IVF divide o espaço vetorial em n partições listadas e cada partição é representada por um centroide
    • A quantização PQ ou SQ é usada por partição para compactar os vetores
    • O gráfico HNSW dos centroides é criado; ele é útil quando o número de centroides é muito grande
  • Os dados são transmitidos do Data Service usando o protocolo DCP e para cada documento recebido.
    • O documento é atribuído à partição cujo centroide está mais próximo do vetor, ou seja, o centroide é C1
  • Durante a indexação, o vetor de cada documento é atribuído ao centroide mais próximo, armazenado em uma forma codificada compacta otimizada para o cálculo rápido da distância e rastreado de forma eficiente para que futuras atualizações só reprocessem o vetor se ele realmente mudar.
Observação

Se a distribuição do vetor subjacente mudar significativamente, o índice deverá ser reconstruído para treinar novamente o índice. Isso pode ocorrer devido a:

  • Uma alteração no modelo de incorporação (por exemplo, troca de modelos ou dimensões)
  • Mudanças importantes na distribuição de dados (novas categorias de produtos, alterações de idioma ou desvio de domínio)
  • Reincorporação de documentos existentes com incorporações atualizadas
Quantos documentos são necessários para treinar um índice vetorial?

Ao criar um índice vetorial, o Couchbase coleta automaticamente amostras de dados vetoriais para treinar o índice para uma pesquisa ANN eficiente e precisa.

Em geral, a coleção deve conter pelo menos tantos documentos quanto o número de centroides (nlist) configurados para o índice, pois cada centroide requer dados de treinamento.

Quando a quantização de produto (PQ) é usada, esse mínimo se torna max(nlist, 2^nbits) para garantir dados suficientes para o treinamento do quantizador, em que nbits é N de PQ{M}x{N}.

O Couchbase lida com o treinamento da seguinte forma:

  • Conjuntos de dados pequenos (até cerca de 10.000 documentos):
    • Todos os vetores são usados para treinamento, não é necessária nenhuma amostragem.
  • Conjuntos de dados maiores:
    • Por padrão, o Couchbase seleciona um conjunto de treinamento tomando o maior dos seguintes, enquanto limita o tamanho da amostra final a 1 milhão de vetores:
      • 10% do conjunto de dados, e
      • 10x o número de centroides (nlist)
    • Essa abordagem equilibra a qualidade do treinamento com o tempo de criação do índice

Melhores práticas: Para obter um treinamento estável e de alta qualidade, busque pelo menos 10 vetores por centroide, o que permite que o índice aprenda a distribuição do vetor subjacente de forma eficaz.

Controle avançado: Se necessário, você pode controlar explicitamente o número de vetores de treinamento especificando o parâmetro train_list ao criar o índice.

O Couchbase gerencia o processo de amostragem e treinamento automaticamente. Como usuário, o principal requisito é garantir que exista um número suficiente de documentos incorporados antes de criar o índice.

Varredura de índice

Fluxo de varredura

Quando chega uma consulta que contém uma pesquisa vetorial, o Couchbase segue uma sequência bem definida para encaminhá-la aos componentes certos e preparar a varredura.

Se os índices vetoriais variáveis tiverem sido criados e estiverem ativos, o Query Service poderá usá-los para atender mais rapidamente às consultas ANN filtradas

O coordenador de varredura no processo do indexador recebe as entradas mencionadas abaixo junto com o nome do índice e os parâmetros de consistência:

  • Filtros escalares em campos indexados
    • Predicados de igualdade ou de intervalo, como sugars_100g < 20
  • O vetor de consulta
    • Incorporação da intenção de pesquisa do usuário
  • O tamanho do resultado k
    • Quantos itens semelhantes o usuário deseja recuperar 
    • Isso é fornecido no LIMIT
  • O número de centroides mais próximos n
    • Quanto do espaço vetorial queremos pesquisar
    • O valor nprobes n é um parâmetro para DISTÂNCIA_APROXIMADA_DO_VETOR

Depois de obter as informações acima, é formada uma solicitação de varredura, que passa pelas seguintes etapas:

  1. O instantâneo do índice é obtido com base nos parâmetros de consistência fornecidos.
    • Se o usuário precisar de consistência de sessão, o indexador buscará o carimbo de data/hora mais recente do Data Service e aguardará que o indexador se atualize e gere instantâneos consistentes que possam atender à consulta.
    • Se o usuário não tiver problemas com qualquer consistência, o indexador usará o instantâneo armazenado em cache sem esperar.
  2. O indexador aguarda os leitores de armazenamento necessários para atender à consulta. 
    • Como os recursos do indexador são limitados, ele é configurado com o número máximo de leitores que podem ser executados; portanto, se um sistema estiver ocupado, as varreduras deverão esperar que os leitores fiquem livres.
  3. O indexador obtém os livros de código para as partições que estão sendo examinadas para a consulta fornecida.
    • Observe que o livro de códigos (lista invertida IVF e livros de códigos PQ) não muda após a fase inicial de treinamento, portanto, não há instantâneos para o livro de códigos.
  4. Usando os livros de códigos obtidos acima, o mais próximo nprobe centroides do vetor de consulta em cada partição necessária são obtidos para um determinado vetor de consulta.
  5. Para uma determinada partição de índice, os filtros escalares e os centróides mais próximos são combinados para formar intervalos de varredura não sobrepostos para ler dados do índice.
  6. Agora, o indexador configura um pipeline de varredura dedicado. Pense nesse pipeline como uma linha de montagem pequena e de curta duração criada especificamente para essa consulta. Os estágios do pipeline (leitura, acumulação e gravação) são executados em paralelo para acelerar o processo de consulta.
Pipeline de varredura

O próprio pipeline de varredura tem três estágios: leitura, agregação e gravação. Como qualquer pipeline, cada estágio é executado em paralelo e transmite sua saída para o próximo.

  1. Estágio de leitura => Varredura paralela + Filtragem escalar
    • O estágio de leitura se espalha por vários trabalhadores de varredura.
    • Cada trabalhador:
      • Faz a varredura e lê o intervalo de índice atribuído.
      • Aplica filtros escalares antecipadamente para eliminar itens irrelevantes.
      • Encaminha apenas os documentos de qualificação para a próxima etapa.
    • Essa poda antecipada é fundamental; ela evita cálculos desnecessários de distância vetorial posteriormente.
  2. Estágio Agregado => Ordenação + Computação da Distância Vetorial
    • O estágio agregado coleta resultados de todos os trabalhadores e realiza o “trabalho pesado”.”
    • Ele mescla e ordena itens, se necessário.
    • Ele substitui as distâncias aproximadas baseadas em centroides por distâncias computadas reais.
    • Ele mantém uma pilha top-k para rastrear os melhores candidatos até o momento.
    • Esse estágio é onde a lógica ANN encontra a filtragem escalar.
  3. Estágio de gravação => Transmissão de resultados de volta ao cliente GSI no serviço de consulta
    • Por fim, o estágio de gravação transmite os resultados agregados para o serviço de consulta.
    • Se o índice for distribuído em vários nós do indexador, os resultados de cada nó serão mesclados.
    • A partir daí, o processador de consultas pode executar operações adicionais, como:
      • Filtragem de granulação grossa
      • JOINs
      • Projeções ou classificação final

Por fim, o usuário recebe uma lista limpa e ordenada dos vizinhos mais próximos que satisfazem todas as condições escalares.

Comportamento avançado de consultas em varreduras de índices vetoriais compostos

Depois de entender como funciona um pipeline de varredura vetorial, há vários conceitos mais profundos que influenciam a eficiência da execução das consultas. Esses comportamentos estão ligados ao modo como o índice é definido e como os predicados escalares interagem com as partições de vetor.

Paralelismo de varredura

Cada consulta tem um limite natural de quanto paralelismo pode ser explorado. Esse paralelismo inerente vem de quantos intervalos de índices não sobrepostos podem ser gerados a partir dos predicados escalares e das nprobes. Mais intervalos disjuntos significam mais oportunidades de varredura em paralelo.

Mas as restrições de escala não são o único fator. O número real de trabalhadores que o sistema usa é o mínimo de:

  • O grau de paralelismo inerente que a consulta pode expor
  • Quantos centroides a consulta precisa pesquisar
  • Quantos centroides o índice contém
  • O máximo configurado de trabalhadores por varredura por partição

Isso evita que o sistema sobrecarregue a CPU ou crie threads desnecessários quando não houver trabalho paralelo adicional a ser feito.

Predicados-chave principais - Onde o paralelismo começa

Os predicados nas chaves principais do índice (os primeiros campos listados na definição do índice composto) determinam o grau de paralelismo que sua consulta pode explorar.

Se uma chave escalar principal tiver vários predicados de igualdade, cada um deles se tornará um intervalo de varredura independente, permitindo que o sistema se espalhe e os execute em paralelo.

If the leading key uses a range predicate, the entire query collapses into one large scan range, which reduces parallelism.

In short:

  • Equality on leading keys → maximum parallelism
  • Range on leading keys → one big sequential scan

Choosing the right leading keys in the index definition has a direct impact on latency.

Vector predicates effectively behave like equality filters on centroid IDs, selecting a fixed set of clusters to scan.

Scalar Selectivity - How Much Work You Don’t Have to Do

Scalar selectivity measures how many data points can be eliminated by a scalar filter.

A highly selective filter removes a large portion of the dataset before vector distance calculations even begin.

Por exemplo:

  • sugars_100g < 20 may eliminate 70% of items
  • proteins_100g > 10 may eliminate 90% of items

The more selective the scalar, the fewer vectors the index must compare.

Composite vector index scan throughput increases proportionally with scalar selectivity, because the pipeline spends less time reading documents and computing distances.

Paginação - Ordered Vector Results

Composite vector index scans produce a global order for the result set.

This happens because the index substitutes centroid IDs with actual vector distances, giving each candidate a precise distance metric.

You can use LIMIT and OFFSET to paginate through results as long as enough qualifying items exist within the selected n centroids.

This makes composite vector indexes suitable for UIs that require infinite scroll or page-by-page product browsing.

Flexibility in Index Definition - Tailor the Index to the Workload

Composite vector index DDL gives you full control over the ordering of index keys.

This order directly affects how filtering is performed, which in turn impacts query performance.

This flexibility enables multiple pruning strategies:

  • Vector-centric pruning
    • Start the index with the vector key, followed by scalars:
      • CREATE INDEX idx ON food(text_vector, sugars_100g, proteins_100g)
    • Good for workloads driven primarily by vector similarity.
  • Scalar-centric pruning
    • Place highly selective scalar fields first, then the vector key:
      • CREATE INDEX idx ON food(sugars_100g, proteins_100g, text_vector)
    • This is the most common and most efficient pattern because selective scalars prune aggressively before vector evaluation begins.
  • Vector-only pruning
    • Create an index only on the vector key:
      • CREATE INDEX idx ON food(text_vector)
    • This is useful when scalar fields have poor selectivity and won’t help prune the search space.
  • Scalar-only pruning
    • Create a traditional non-vector index for queries that don’t use vector similarity.
Scalar-Only Query Support and Covering Scans

When the scalar predicates in a query are sargable against the scalar keys of a composite vector index, the index can be used to serve purely scalar queries - even when no vector similarity condition is present. In such cases, the composite vector index behaves like a traditional secondary index and can act as a covering index, allowing the query to be satisfied entirely from the index without fetching documents from the Data Service.

The scalar-only query:

Is sargable for: 

And not for:

This is because: 

  • The leading key is a vector
  • GSI cannot seek or range-scan on it
  • The index cannot be used efficiently for scalar predicates

Up to this point, we’ve seen how composite vector indexes combine scalar pruning with vector similarity efficiently. But similarity alone is rarely sufficient in real applications. What happens when you want results that are both semantically close to a query and ordered according to application-specific signals such as nutrition, price, or freshness, without pulling large result sets back to the query layer?

In the next part of this series, we’ll dive into Filtered ANN Search With Composite Vector Indexes and show how Couchbase pushes complex ORDER BY and LIMIT semantics directly into the indexer, allowing distance-based similarity and scalar ordering to be evaluated together in a single, efficient execution path.

Compartilhe este artigo
Receba atualizações do blog do Couchbase em sua caixa de entrada
Esse campo é obrigatório.

Autor

Postado por Sai Kommaraju

Deixe um comentário

Pronto para começar a usar o Couchbase Capella?

Iniciar a construção

Confira nosso portal do desenvolvedor para explorar o NoSQL, procurar recursos e começar a usar os tutoriais.

Use o Capella gratuitamente

Comece a trabalhar com o Couchbase em apenas alguns cliques. O Capella DBaaS é a maneira mais fácil e rápida de começar.

Entre em contato

Deseja saber mais sobre as ofertas do Couchbase? Deixe-nos ajudar.