Esta página explica como criar e gerenciar índices de vetores do Spanner, que usam a pesquisa aproximada do vizinho mais próximo (ANN) e estruturas baseadas em árvores para acelerar as pesquisas de similaridade de vetores nos seus dados.
O Spanner acelera as pesquisas de vetores de vizinho mais próximo aproximado (ANN) usando um índice de vetor especializado. Esse índice usa o vizinho mais próximo escalonável (ScaNN) do Google Research, um algoritmo de vizinho mais próximo altamente eficiente.
O índice de vetor usa uma estrutura baseada em árvore para particionar dados e facilitar pesquisas mais rápidas. O Spanner oferece configurações de árvore de dois e três níveis:
- Configuração de árvore de dois níveis: os nós folha (
num_leaves
) contêm grupos de vetores estreitamente relacionados e o centroide correspondente. O nível raiz consiste nos centroides de todos os nós folha. - Configuração de árvore de três níveis: semelhante em conceito a uma árvore de dois níveis, mas introduzindo uma camada de ramificação adicional (
num_branches
), de onde os centroides do nó folha são ainda mais particionados para formar o nível raiz (num_leaves
).
O Spanner escolhe um índice para você. No entanto, se você souber que um
índice específico funciona melhor, use a dica FORCE_INDEX
para escolher o índice vetorial mais adequado ao seu caso de uso.
Para mais informações, consulte as instruções VECTOR INDEX
.
Limitações
- Não é possível pré-dividir índices de vetores. Para mais informações, consulte Visão geral da pré-divisão.
Criar índice de vetor
Para otimizar o recall e a performance de um índice de vetor, recomendamos que você:
Crie o índice de vetor depois que a maioria das linhas com embeddings for gravada no banco de dados. Talvez seja necessário reconstruir periodicamente o índice de vetor depois de inserir novos dados. Para mais informações, consulte Reconstruir o índice vetorial.
Use a cláusula
STORING
para armazenar uma cópia de uma coluna no índice de vetor. Se um valor de coluna for armazenado no índice de vetor, o Spanner vai realizar a filtragem no nível da folha do índice para melhorar a performance da consulta. Recomendamos que você armazene uma coluna se ela for usada em uma condição de filtragem. Para mais informações sobre como usarSTORING
em um índice, consulte Criar um índice para verificações somente de índice.
Ao criar a tabela, a coluna de incorporação precisa ser uma matriz do tipo de dados FLOAT32
(recomendado) ou FLOAT64
e ter uma anotação vector_length, indicando a dimensão dos vetores.
A instrução DDL a seguir cria uma tabela Documents
com uma coluna de embedding DocEmbedding
com um comprimento de vetor:
CREATE TABLE Documents (
UserId INT64 NOT NULL,
DocId INT64 NOT NULL,
Author STRING (1024),
DocContents Bytes(MAX),
DocEmbedding ARRAY<FLOAT32>(vector_length=>128) NOT NULL,
NullableDocEmbedding ARRAY<FLOAT32>(vector_length=>128),
WordCount INT64,
) PRIMARY KEY (DocId);
Depois de preencher a tabela Documents
, crie um índice de vetor com uma árvore de dois níveis e 1.000 nós folha na tabela Documents
com uma coluna de embedding DocEmbedding
usando a distância de cosseno:
CREATE VECTOR INDEX DocEmbeddingIndex
ON Documents(DocEmbedding)
STORING (WordCount)
OPTIONS (distance_type = 'COSINE', tree_depth = 2, num_leaves = 1000);
Se a coluna de embedding não estiver marcada como NOT NULL
na definição da tabela, declare-a com uma cláusula WHERE COLUMN_NAME IS NOT NULL
na definição do índice de vetor, em que COLUMN_NAME
é o nome da coluna de embedding. Para
criar um índice de vetor com uma árvore de três níveis e 1.000.000 nós folha na
coluna de embedding anulável NullableDocEmbedding
usando a distância de cosseno:
CREATE VECTOR INDEX DocEmbeddingThreeLevelIndex
ON Documents(NullableDocEmbedding)
STORING (WordCount)
WHERE NullableDocEmbedding IS NOT NULL
OPTIONS (distance_type = 'COSINE', tree_depth = 3, num_branches=1000, num_leaves = 1000000);
Filtrar um índice vetorial
Também é possível criar um índice de vetor filtrado para encontrar os itens mais semelhantes no banco de dados que correspondem à condição de filtro. Um índice de vetor filtrado indexa seletivamente as linhas que atendem às condições de filtro especificadas, melhorando o desempenho da pesquisa.
No exemplo a seguir, a tabela Documents2
tem uma coluna chamada Category
.
Na nossa pesquisa vetorial, queremos indexar a categoria "Tecnologia". Por isso, criamos uma coluna gerada que resulta em NULL
se a condição de categoria não for atendida.
CREATE TABLE Documents2 (
DocId INT64 NOT NULL,
Category STRING(MAX),
NullIfFiltered BOOL AS (IF(Category = 'Tech', TRUE, NULL)) HIDDEN,
DocEmbedding ARRAY<FLOAT32>(vector_length=>128),
) PRIMARY KEY (DocId);
Em seguida, criamos um índice vetorial com um filtro. O índice de vetor TechDocEmbeddingIndex
indexa apenas documentos na categoria "Tecnologia".
CREATE VECTOR INDEX TechDocEmbeddingIndex
ON Documents2(DocEmbedding)
STORING(NullIfFiltered)
WHERE DocEmbedding IS NOT NULL AND NullIfFiltered IS NOT NULL
OPTIONS (...);
Quando o Spanner executa a consulta a seguir, que tem filtros que
correspondem a TechDocEmbeddingIndex
, ele escolhe e é acelerado automaticamente por
TechDocEmbeddingIndex
. A consulta pesquisa apenas documentos na categoria "Tecnologia". Também é possível usar {@FORCE_INDEX=TechDocEmbeddingIndex}
para forçar o Spanner a usar TechDocEmbeddingIndex
explicitamente.
SELECT *
FROM Documents2
WHERE DocEmbedding IS NOT NULL AND NullIfFiltered IS NOT NULL
ORDER BY APPROX_(....)
LIMIT 10;
A seguir
Saiba mais sobre os vizinhos mais próximos aproximados do Spanner.
Saiba mais sobre as funções GoogleSQL
APPROXIMATE_COSINE_DISTANCE()
,APPROXIMATE_EUCLIDEAN_DISTANCE()
,APPROXIMATE_DOT_PRODUCT()
.Saiba mais sobre as instruções
VECTOR INDEX
do GoogleSQL.Saiba mais sobre as práticas recomendadas de índice vetorial.