Faça a gestão dos índices vetoriais
Este documento descreve como criar e gerir índices vetoriais para acelerar as suas pesquisas vetoriais.
Um índice vetorial é uma estrutura de dados concebida para permitir que a função VECTOR_SEARCH
seja executada de forma mais eficiente, especialmente em grandes conjuntos de dados.
Quando usa um índice, o VECTOR_SEARCH
usa algoritmos de vizinho mais próximo aproximado (ANN) para reduzir a latência das consultas e o custo computacional. Embora a RAA introduza um grau de aproximação, o que significa que a relembrança pode não ser de 100%, as melhorias de desempenho oferecem normalmente uma vantagem para a maioria das aplicações.
Funções e permissões
Para criar um índice vetorial, precisa da bigquery.tables.createIndex
autorização de IAM na tabela onde está a criar o índice. Para eliminar um índice vetorial, precisa da autorização bigquery.tables.deleteIndex
. Cada uma das seguintes funções de IAM predefinidas inclui as autorizações de que precisa para trabalhar com índices de vetores:
- Proprietário de dados do BigQuery (
roles/bigquery.dataOwner
) - Editor de dados do BigQuery (
roles/bigquery.dataEditor
)
Escolha um tipo de índice vetorial
O BigQuery oferece dois tipos de índice vetorial, IVF e
TreeAH, cada um deles a suportar
diferentes exemplos de utilização. O BigQuery suporta o processamento em lote para a pesquisa vetorial através do processamento de várias linhas dos dados de entrada na função VECTOR_SEARCH
.
Para pequenos lotes de consultas, os índices IVF são preferíveis. Para grandes lotes de consultas,
os índices TreeAH, criados com o
algoritmo ScaNN da Google,
são preferíveis.
IVF Index
O IVF é um índice de ficheiros invertidos que usa um algoritmo k-means para agrupar os dados vetoriais e, em seguida, divide os dados vetoriais com base nesses grupos. A
VECTOR_SEARCH
função
pode usar estas partições para reduzir a quantidade de dados que precisa de ler para
determinar um resultado.
TreeAH Index
O tipo de índice TreeAH tem o nome devido à combinação de uma estrutura semelhante a uma árvore e à utilização de hashing assimétrico (AH), uma técnica de quantização essencial do algoritmo ScaNN subjacente. Um índice TreeAH funciona da seguinte forma:
- A tabela base é dividida em fragmentos mais pequenos e mais fáceis de gerir.
- É preparado um modelo de clustering com o número de clusters derivado da opção
leaf_node_embedding_count
no argumentotree_ah_options
da declaraçãoCREATE VECTOR INDEX
. - Os vetores são comprimidos com a quantização de produtos, uma técnica que reduz a respetiva utilização de memória. Os vetores comprimidos são, em seguida, armazenados nas tabelas de índice em vez dos vetores originais, o que reduz os tamanhos dos índices de vetores.
- Quando a função
VECTOR_SEARCH
é executada, é calculada de forma eficiente uma lista de candidatos para cada vetor de consulta usando a hash assimétrica, que é otimizada por hardware para cálculos de distância aproximados. Estes candidatos são, em seguida, reclassificados e reordenados com base em incorporações exatas.
O algoritmo TreeAH está otimizado para consultas em lote que processam centenas ou mais vetores de consulta. A utilização da quantização de produtos pode reduzir significativamente a latência e o custo, potencialmente em ordens de magnitude em comparação com o IVF. No entanto, devido ao aumento dos custos gerais, o algoritmo IVF pode ser melhor quando tem um número menor de vetores de consulta.
Sugerimos que experimente o tipo de índice TreeAH se o seu exemplo de utilização cumprir os seguintes critérios:
A sua tabela contém 200 milhões de linhas ou menos.
Executa frequentemente consultas em lote grandes que envolvem centenas ou mais vetores de consulta.
Para consultas de pequenos lotes com o tipo de índice TreeAH, VECTOR_SEARCH
pode
reverter para
pesquisa de força bruta.
Quando isto ocorre, é fornecido um
IndexUnusedReason
para explicar por que motivo o índice de vetores não foi usado.
Crie um índice vetorial IVF
Para criar um índice vetorial IVF, use a declaração de linguagem de definição de dados (LDD):
CREATE VECTOR INDEX
Aceda à página do BigQuery.
No editor de consultas, execute a seguinte declaração SQL:
Para criar um índice vetorial IVF:
CREATE [ OR REPLACE ] VECTOR INDEX [ IF NOT EXISTS ] INDEX_NAME ON DATASET_NAME.TABLE_NAME(COLUMN_NAME) STORING(STORED_COLUMN_NAME [, ...]) OPTIONS(index_type = 'IVF', distance_type = 'DISTANCE_TYPE', ivf_options = '{"num_lists":NUM_LISTS}')
Substitua o seguinte:
INDEX_NAME
: o nome do índice vetorial que está a criar. Uma vez que o índice é sempre criado no mesmo projeto e conjunto de dados que a tabela base, não é necessário especificá-los no nome.DATASET_NAME
: o nome do conjunto de dados que contém a tabela.TABLE_NAME
: o nome da tabela que contém a coluna com dados de incorporações.COLUMN_NAME
: o nome de uma coluna que contém os dados de incorporações. A coluna tem de ter o tipoARRAY<FLOAT64>
. A coluna não pode ter campos secundários. Todos os elementos na matriz têm de ser nãoNULL
, e todos os valores na coluna têm de ter as mesmas dimensões da matriz.STORED_COLUMN_NAME
: o nome de uma coluna de nível superior na tabela para armazenar no índice de vetores. O tipo de coluna não pode serRANGE
. As colunas armazenadas não são usadas se a tabela tiver uma política de acesso ao nível da linha ou a coluna tiver uma etiqueta de política. Para informações sobre como ativar colunas armazenadas, consulte Armazene colunas e pré-filtre.DISTANCE_TYPE
: especifica o tipo de distância predefinido a usar quando efetuar uma pesquisa vetorial com este índice. Os valores suportados sãoEUCLIDEAN
,COSINE
eDOT_PRODUCT
.EUCLIDEAN
é a predefinição.A criação do índice usa sempre a distância
EUCLIDEAN
para a preparação, mas a distância usada na funçãoVECTOR_SEARCH
pode ser diferente.Se especificar um valor para o argumento
distance_type
da funçãoVECTOR_SEARCH
, esse valor é usado em vez do valorDISTANCE_TYPE
.NUM_LISTS
: um valorINT64
que especifica o número de listas que o índice IVF agrupa e, em seguida, divide os dados vetoriais. Este valor tem de ser igual ou inferior a 5000. Durante a indexação, são atribuídos vetores à lista correspondente ao centroide do cluster mais próximo. Se omitir este argumento, o BigQuery determina um valor predefinido com base nas características dos seus dados. O valor predefinido funciona bem para a maioria dos exemplos de utilização.NUM_LISTS
controla o nível de detalhe do ajuste das consultas. Os valores mais elevados criam mais listas, pelo que pode definir a opçãofraction_lists_to_search
da funçãoVECTOR_SEARCH
para analisar uma percentagem menor do índice. Por exemplo, analisar 1% de 100 listas em vez de analisar 10% de 10 listas. Isto permite um controlo mais preciso da velocidade de pesquisa e da capacidade de memorização, mas aumenta ligeiramente o custo de indexação. Defina este valor do argumento com base na precisão com que precisa de ajustar o âmbito da consulta.
O exemplo seguinte cria um índice vetorial na coluna embedding
de my_table
:
CREATE TABLE my_dataset.my_table(embedding ARRAY<FLOAT64>); CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding) OPTIONS(index_type = 'IVF');
O exemplo seguinte cria um índice vetorial na coluna embedding
de my_table
e especifica o tipo de distância a usar e as opções de IVF:
CREATE TABLE my_dataset.my_table(embedding ARRAY<FLOAT64>); CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding) OPTIONS(index_type = 'IVF', distance_type = 'COSINE', ivf_options = '{"num_lists": 2500}')
Crie um índice vetorial TreeAH
Para criar um índice vetorial TreeAH, use a declaração de linguagem de definição de dados (LDD):CREATE VECTOR INDEX
Aceda à página do BigQuery.
No editor de consultas, execute a seguinte declaração SQL:
CREATE [ OR REPLACE ] VECTOR INDEX [ IF NOT EXISTS ] INDEX_NAME ON DATASET_NAME.TABLE_NAME(COLUMN_NAME) STORING(STORED_COLUMN_NAME [, ...]) OPTIONS(index_type = 'TREE_AH', distance_type = 'DISTANCE_TYPE', tree_ah_options = '{"leaf_node_embedding_count":LEAF_NODE_EMBEDDING_COUNT, "normalization_type":"NORMALIZATION_TYPE"}')
Substitua o seguinte:
INDEX_NAME
: o nome do índice vetorial que está a criar. Uma vez que o índice é sempre criado no mesmo projeto e conjunto de dados que a tabela base, não é necessário especificá-los no nome.DATASET_NAME
: o nome do conjunto de dados que contém a tabela.TABLE_NAME
: o nome da tabela que contém a coluna com dados de incorporações.COLUMN_NAME
: o nome de uma coluna que contém os dados de incorporações. A coluna tem de ter o tipoARRAY<FLOAT64>
. A coluna não pode ter campos secundários. Todos os elementos na matriz têm de ser nãoNULL
, e todos os valores na coluna têm de ter as mesmas dimensões da matriz.STORED_COLUMN_NAME
: o nome de uma coluna de nível superior na tabela para armazenar no índice de vetores. O tipo de coluna não pode serRANGE
. As colunas armazenadas não são usadas se a tabela tiver uma política de acesso ao nível da linha ou a coluna tiver uma etiqueta de política. Para informações sobre como ativar colunas armazenadas, consulte Armazene colunas e pré-filtre.DISTANCE_TYPE
: um argumento opcional que especifica o tipo de distância predefinido a usar quando efetuar uma pesquisa vetorial com este índice. Os valores suportados sãoEUCLIDEAN
,COSINE
eDOT_PRODUCT
.EUCLIDEAN
é a predefinição.A criação do índice usa sempre a distância
EUCLIDEAN
para a preparação, mas a distância usada na funçãoVECTOR_SEARCH
pode ser diferente.Se especificar um valor para o argumento
distance_type
da funçãoVECTOR_SEARCH
, esse valor é usado em vez do valorDISTANCE_TYPE
.LEAF_NODE_EMBEDDING_COUNT
: um valorINT64
superior ou igual a 500 que especifica o número aproximado de vetores em cada nó folha da árvore que o algoritmo TreeAH cria. O algoritmo TreeAH divide todo o espaço de dados num número de listas, com cada lista a conter aproximadamenteLEAF_NODE_EMBEDDING_COUNT
pontos de dados. Um valor inferior cria mais listas com menos pontos de dados, enquanto um valor superior cria menos listas com mais pontos de dados. A predefinição é 1000, o que é adequado para a maioria dos conjuntos de dados.NORMALIZATION_TYPE
: um valor deSTRING
. Os valores suportados sãoNONE
ouL2
. A predefinição éNONE
. A normalização ocorre antes de qualquer processamento, tanto para os dados da tabela base como para os dados de consulta, mas não modifica a coluna de incorporaçãoCOLUMN_NAME
emTABLE_NAME
. Consoante o conjunto de dados, o modelo de incorporação e o tipo de distância usados durante aVECTOR_SEARCH
, a normalização das incorporações pode melhorar a capacidade de memorização.
O exemplo seguinte cria um índice vetorial na coluna embedding
de my_table
e especifica o tipo de distância a usar e as opções TreeAH:
CREATE TABLE my_dataset.my_table(id INT64, embedding ARRAY<FLOAT64>); CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding) OPTIONS (index_type = 'TREE_AH', distance_type = 'EUCLIDEAN', tree_ah_options = '{"normalization_type": "L2"}');
Filtragem
As secções seguintes explicam como os pré-filtros e os pós-filtros afetam os resultados da pesquisa vetorial, bem como a forma de pré-filtrar através da utilização de colunas armazenadas e partições no índice vetorial.
Pré-filtros e pós-filtros
Nas operações do BigQuery, a filtragem prévia e a filtragem posterior servem para refinar os resultados da pesquisa, aplicando condições com base nas colunas de metadados associadas às incorporações de vetores.VECTOR_SEARCH
É importante
compreender as diferenças, a implementação e o impacto para otimizar
o desempenho, o custo e a precisão das consultas.
A pré-filtragem e a pós-filtragem são definidas da seguinte forma:
- Pré-filtragem: aplica condições de filtro antes de a pesquisa do vizinho mais próximo aproximado (ANN) realizar cálculos de distância em vetores candidatos. Isto restringe o conjunto de vetores que são considerados durante a pesquisa. Consequentemente, a pré-filtragem resulta frequentemente em tempos de consulta mais rápidos e num custo computacional reduzido, uma vez que a pesquisa de ANN avalia menos potenciais candidatos.
- Pós-filtragem: aplica condições de filtro após a identificação dos
top_k
vizinhos mais próximos iniciais pela pesquisa ANN. Isto refina o conjunto de resultados final com base nos critérios especificados.
O posicionamento da cláusula WHERE
determina se um filtro funciona como um pré-filtro ou um pós-filtro.
Para criar um pré-filtro, a cláusula WHERE
da consulta tem de se aplicar ao argumento da tabela base da função VECTOR_SEARCH
.
O predicado tem de se aplicar a uma coluna armazenada. Caso contrário, torna-se efetivamente um filtro posterior.
O exemplo seguinte mostra como criar um pré-filtro:
-- Pre-filter on a stored column. The index speeds up the query. SELECT * FROM VECTOR_SEARCH( (SELECT * FROM my_dataset.my_table WHERE type = 'animal'), 'embedding', TABLE my_dataset.my_testdata); -- Filter on a column that isn't stored. The index is used to search the -- entire table, and then the results are post-filtered. You might see fewer -- than 5 matches returned for some embeddings. SELECT query.test_id, base.type, distance FROM VECTOR_SEARCH( (SELECT * FROM my_dataset.my_table WHERE id = 123), 'embedding', TABLE my_dataset.my_testdata, top_k => 5); -- Use pre-filters with brute force. The data is filtered and then searched -- with brute force for exact results. SELECT query.test_id, base.type, distance FROM VECTOR_SEARCH( (SELECT * FROM my_dataset.my_table WHERE id = 123), 'embedding', TABLE my_dataset.my_testdata, options => '{"use_brute_force":true}');
Para criar um filtro posterior, a cláusula WHERE
da consulta tem de ser aplicada fora
da função VECTOR_SEARCH
, para que filtre os resultados devolvidos pela
pesquisa.
O exemplo seguinte mostra como criar um filtro posterior:
-- Use post-filters. The index is used, but the entire table is searched and -- the post-filtering might reduce the number of results. SELECT query.test_id, base.type, distance FROM VECTOR_SEARCH( TABLE my_dataset.my_table, 'embedding', TABLE my_dataset.my_testdata, top_k => 5) WHERE base.type = 'animal'; SELECT base.id, distance FROM VECTOR_SEARCH( TABLE mydataset.base_table, 'embedding', (SELECT embedding FROM mydataset.query_table), top_k => 10 ) WHERE type = 'document' AND year > 2022
Quando usa a filtragem posterior ou quando os filtros da tabela base especificados
fazem referência a colunas não armazenadas e, por isso, atuam como filtros posteriores, o conjunto de resultados
final pode conter menos de top_k
linhas, potencialmente até zero linhas,
se o predicado for seletivo. Se precisar de um número específico de resultados após a filtragem, considere especificar um valor top_k
maior ou aumentar o valor fraction_lists_to_search
na chamada VECTOR_SEARCH
.
Em alguns casos, especialmente se o pré-filtro for muito seletivo, a pré-filtragem também pode reduzir o tamanho do conjunto de resultados. Se isto acontecer, experimente aumentar o valor de fraction_lists_to_search
na chamada VECTOR_SEARCH
.
Pré-filtre com colunas armazenadas
Para melhorar ainda mais a eficiência do seu índice vetorial, pode especificar colunas da tabela base para armazenar no índice vetorial. A utilização de colunas armazenadas pode otimizar as consultas que chamam a função VECTOR_SEARCH
das seguintes formas:
Em vez de pesquisar numa tabela inteira, pode chamar a função
VECTOR_SEARCH
numa declaração de consulta que pré-filtra a tabela base com uma cláusulaWHERE
. Se a sua tabela tiver um índice e filtrar apenas colunas armazenadas, o BigQuery otimiza a consulta filtrando os dados antes da pesquisa e, em seguida, usando o índice para pesquisar o conjunto de resultados mais pequeno. Se filtrar por colunas que não estão armazenadas, o BigQuery aplica o filtro após a pesquisa da tabela ou pós-filtros.A função
VECTOR_SEARCH
gera uma struct denominadabase
que contém todas as colunas da tabela base. Sem colunas armazenadas, é necessária uma junção potencialmente cara para obter as colunas armazenadas embase
. Se usar um índice IVF e a sua consulta selecionar apenas colunas armazenadas debase
, o BigQuery otimiza a consulta para eliminar essa junção. Para os índices TreeAH, a junção com a tabela base não é removida. As colunas armazenadas nos índices TreeAH são usadas apenas para fins de pré-filtragem.
Para armazenar colunas, liste-as na cláusula STORING
da declaração CREATE VECTOR INDEX
.
O armazenamento de colunas aumenta o tamanho do índice vetorial, pelo que é melhor armazenar apenas as colunas usadas ou filtradas com maior frequência.
O exemplo seguinte cria um índice vetorial com colunas armazenadas e, em seguida, executa uma consulta de pesquisa vetorial que seleciona apenas colunas armazenadas:
-- Create a table that contains an embedding. CREATE TABLE my_dataset.my_table(embedding ARRAY<FLOAT64>, type STRING, creation_time DATETIME, id INT64); -- Create a query table that contains an embedding. CREATE TABLE my_dataset.my_testdata(embedding ARRAY<FLOAT64>, test_id INT64); -- Create a vector index with stored columns. CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding) STORING (type, creation_time) OPTIONS (index_type = 'IVF'); -- Select only stored columns from a vector search to avoid an expensive join. SELECT query, base.type, distance FROM VECTOR_SEARCH( TABLE my_dataset.my_table, 'embedding' TABLE my_dataset.my_testdata);
Limitações de colunas armazenadas
- Se o modo, o tipo ou o esquema de uma coluna for alterado na tabela base e se for uma coluna armazenada no índice vetorial, pode haver um atraso antes de essa alteração ser refletida no índice vetorial. Até que as atualizações sejam aplicadas ao índice, as consultas de pesquisa vetorial usam as colunas armazenadas modificadas da tabela base.
- Se selecionar uma coluna do tipo
STRUCT
na saída de uma consultaVECTOR_SEARCH
numa tabela que tenha um índice com colunas armazenadas, toda a consulta pode falhar.query
Pré-filtragem com partições
Se a tabela na qual está a criar o índice de vetores estiver particionada, pode optar por particionar também o índice de vetores. A partição do índice de vetores tem as seguintes vantagens:
- A eliminação de partições é aplicada aos índices vetoriais, além das partições da tabela. A eliminação de partições ocorre quando a pesquisa vetorial usa um filtro de qualificação no valor da coluna de particionamento. Isto permite ao BigQuery analisar as partições que correspondem ao filtro e ignorar as partições restantes. O corte de partições pode diminuir os custos de E/S. Para mais informações sobre a eliminação de partições, consulte o artigo Consultar tabelas particionadas.
- É menos provável que a pesquisa vetorial perca resultados se pré-filtrar na coluna de particionamento.
Só pode particionar índices vetoriais TreeAH.
A partição de um índice vetorial só é recomendada se usar a pré-filtragem para limitar a maioria das suas pesquisas vetoriais a algumas partições.
Para criar um índice particionado, use a cláusula PARTITION BY
da declaração CREATE VECTOR INDEX
. A cláusula
PARTITION BY
que especificar na declaração CREATE VECTOR INDEX
tem de ser igual à cláusula PARTITION BY
especificada na
declaração CREATE TABLE
da tabela na qual está a criar o índice vetorial, conforme mostrado no
exemplo seguinte:
-- Create a date-partitioned table. CREATE TABLE my_dataset.my_table( embeddings ARRAYid INT64, date DATE, ) PARTITION BY date; -- Create a partitioned vector index on the table. CREATE VECTOR INDEX my_index ON my_dataset.my_table(embeddings) PARTITION BY date OPTIONS(index_type='TREE_AH', distance_type='COSINE');
Se a tabela usar a partição de colunas de intervalo de números inteiros ou de unidades de tempo, a coluna de partição é armazenada no índice vetorial, o que aumenta o custo de armazenamento.
Se uma coluna de tabela for usada nas cláusulas STORING
e PARTITION BY
da declaração CREATE VECTOR INDEX
, a coluna é armazenada apenas uma vez.
Para usar a partição do índice vetorial, filtre a coluna de partição na subconsulta da tabela base da declaração VECTOR_SEARCH
. No exemplo seguinte,
a tabela samples.items
é particionada pela coluna produced_date
,
pelo que a subconsulta da tabela base na declaração VECTOR_SEARCH
filtra a coluna produced_date
:
SELECT query.id, base.id, distance FROM VECTOR_SEARCH( (SELECT * FROM my_dataset.my_table WHERE produced_date = '2025-01-01'), 'embedding', TABLE samples.test, distance_type => 'COSINE', top_k => 10 );
Exemplos
Crie um índice vetorial particionado numa tabela particionada por data/hora:
-- Create a datetime-partitioned table. CREATE TABLE my_dataset.my_table( id INT64, produced_date DATETIME, embeddings ARRAY) PARTITION BY produced_date; -- Create a partitioned vector index on the table. CREATE VECTOR INDEX index0 ON my_dataset.my_table(embeddings) PARTITION BY produced_date OPTIONS(index_type='TREE_AH', distance_type='COSINE');
Crie um índice vetorial particionado numa tabela particionada por data/hora:
-- Create a timestamp-partitioned table. CREATE TABLE my_dataset.my_table( id INT64, produced_time TIMESTAMP, embeddings ARRAY) PARTITION BY TIMESTAMP_TRUNC(produced_time, HOUR); -- Create a partitioned vector index on the table. CREATE VECTOR INDEX index0 ON my_dataset.my_table(embeddings) PARTITION BY TIMESTAMP_TRUNC(produced_time, HOUR) OPTIONS(index_type='TREE_AH', distance_type='COSINE');
Crie um índice de vetores particionado numa tabela particionada por intervalo de números inteiros:
-- Create a integer range-partitioned table. CREATE TABLE my_dataset.my_table( id INT64, embeddings ARRAY) PARTITION BY RANGE_BUCKET(id, GENERATE_ARRAY(-100, 100, 20)); -- Create a partitioned vector index on the table. CREATE VECTOR INDEX index0 ON my_dataset.my_table(embeddings) PARTITION BY RANGE_BUCKET(id, GENERATE_ARRAY(-100, 100, 20)) OPTIONS(index_type='TREE_AH', distance_type='COSINE');
Crie um índice de vetores particionado numa tabela particionada por tempo de ingestão:
-- Create a ingestion time-partitioned table. CREATE TABLE my_dataset.my_table( id INT64, embeddings ARRAY) PARTITION BY TIMESTAMP_TRUNC(_PARTITIONTIME, DAY); -- Create a partitioned vector index on the table. CREATE VECTOR INDEX index0 ON my_dataset.my_table(embeddings) PARTITION BY TIMESTAMP_TRUNC(_PARTITIONTIME, DAY) OPTIONS(index_type='TREE_AH', distance_type='COSINE');
Limitações da pré-filtragem
- Não pode usar vistas lógicas no pré-filtro.
- Se o pré-filtro contiver uma subconsulta, pode interferir com a utilização do índice.
Compreender quando os dados são indexados
Os índices vetoriais são totalmente geridos pelo BigQuery e são atualizados automaticamente quando a tabela indexada é alterada.
A indexação é assíncrona. Existe um atraso entre a adição de novas linhas à tabela base e a apresentação das novas linhas no índice. No entanto, a função VECTOR_SEARCH
continua a ter em conta todas as linhas e não perde linhas não indexadas. A função pesquisa através do índice os registos indexados e usa a pesquisa de força bruta para os registos que ainda não estão indexados.
Se criar um índice vetorial numa tabela com menos de 10 MB, o índice vetorial não é preenchido. Da mesma forma, se eliminar dados de uma tabela indexada e o tamanho da tabela ficar abaixo de 10 MB, o índice de vetores é desativado temporariamente. Neste caso, as consultas de pesquisa vetorial não usam o índice e o código indexUnusedReasons
na secção vectorSearchStatistics
do recurso Job
é BASE_TABLE_TOO_SMALL
. Sem o índice,
VECTOR_SEARCH
recorre automaticamente à utilização da força bruta para encontrar os
vizinhos mais próximos das incorporações.
Se eliminar a coluna indexada numa tabela ou mudar o nome da própria tabela, o índice de vetores é eliminado automaticamente.
Monitorizar o estado dos índices vetoriais
Pode monitorizar o estado dos seus índices vetoriais consultando as visualizações INFORMATION_SCHEMA
. As seguintes vistas contêm metadados sobre índices vetoriais:
A vista
INFORMATION_SCHEMA.VECTOR_INDEXES
tem informações sobre os índices vetoriais num conjunto de dados.Após a conclusão da declaração
CREATE VECTOR INDEX
, o índice tem de ser preenchido antes de o poder usar. Pode usar as colunaslast_refresh_time
ecoverage_percentage
para verificar a disponibilidade de um índice de vetores. Se o índice vetorial não estiver pronto, pode continuar a usar a funçãoVECTOR_SEARCH
numa tabela, mas pode ser executada mais lentamente sem o índice.A vista
INFORMATION_SCHEMA.VECTOR_INDEX_COLUMNS
tem informações sobre as colunas indexadas por vetores para todas as tabelas num conjunto de dados.A
INFORMATION_SCHEMA.VECTOR_INDEX_OPTIONS
vista tem informações sobre as opções usadas pelos índices vetoriais num conjunto de dados.
Exemplos de índices vetoriais
O exemplo seguinte mostra todos os índices vetoriais ativos em tabelas no conjunto de dados
my_dataset
, localizados no projeto my_project
. Inclui os respetivos nomes, as declarações DDL usadas para os criar e a percentagem de cobertura. Se uma tabela base indexada tiver menos de 10 MB, o respetivo índice não é preenchido. Nesse caso, o valor coverage_percentage
é 0.
SELECT table_name, index_name, ddl, coverage_percentage FROM my_project.my_dataset.INFORMATION_SCHEMA.VECTOR_INDEXES WHERE index_status = 'ACTIVE';
O resultado é semelhante ao seguinte:
+------------+------------+-------------------------------------------------------------------------------------------------+---------------------+ | table_name | index_name | ddl | coverage_percentage | +------------+------------+-------------------------------------------------------------------------------------------------+---------------------+ | table1 | indexa | CREATE VECTOR INDEX `indexa` ON `my_project.my_dataset.table1`(embeddings) | 100 | | | | OPTIONS (distance_type = 'EUCLIDEAN', index_type = 'IVF', ivf_options = '{"num_lists": 100}') | | +------------+------------+-------------------------------------------------------------------------------------------------+---------------------+ | table2 | indexb | CREATE VECTOR INDEX `indexb` ON `my_project.my_dataset.table2`(vectors) | 42 | | | | OPTIONS (distance_type = 'COSINE', index_type = 'IVF', ivf_options = '{"num_lists": 500}') | | +------------+------------+-------------------------------------------------------------------------------------------------+---------------------+ | table3 | indexc | CREATE VECTOR INDEX `indexc` ON `my_project.my_dataset.table3`(vectors) | 98 | | | | OPTIONS (distance_type = 'DOT_PRODUCT', index_type = 'TREE_AH', | | | | | tree_ah_options = '{"leaf_node_embedding_count": 1000, "normalization_type": "NONE"}') | | +------------+------------+-------------------------------------------------------------------------------------------------+---------------------+
Exemplos de colunas de índice vetorial
A seguinte consulta extrai informações sobre colunas que têm índices vetoriais:
SELECT table_name, index_name, index_column_name, index_field_path FROM my_project.dataset.INFORMATION_SCHEMA.VECTOR_INDEX_COLUMNS;
O resultado é semelhante ao seguinte:
+------------+------------+-------------------+------------------+ | table_name | index_name | index_column_name | index_field_path | +------------+------------+-------------------+------------------+ | table1 | indexa | embeddings | embeddings | | table2 | indexb | vectors | vectors | | table3 | indexc | vectors | vectors | +------------+------------+-------------------+------------------+
Exemplos de opções de índice vetorial
A seguinte consulta extrai informações sobre as opções do índice vetorial:
SELECT table_name, index_name, option_name, option_type, option_value FROM my_project.dataset.INFORMATION_SCHEMA.VECTOR_INDEX_OPTIONS;
O resultado é semelhante ao seguinte:
+------------+------------+------------------+------------------+-------------------------------------------------------------------+ | table_name | index_name | option_name | option_type | option_value | +------------+------------+------------------+------------------+-------------------------------------------------------------------+ | table1 | indexa | index_type | STRING | IVF | | table1 | indexa | distance_type | STRING | EUCLIDEAN | | table1 | indexa | ivf_options | STRING | {"num_lists": 100} | | table2 | indexb | index_type | STRING | IVF | | table2 | indexb | distance_type | STRING | COSINE | | table2 | indexb | ivf_options | STRING | {"num_lists": 500} | | table3 | indexc | index_type | STRING | TREE_AH | | table3 | indexc | distance_type | STRING | DOT_PRODUCT | | table3 | indexc | tree_ah_options | STRING | {"leaf_node_embedding_count": 1000, "normalization_type": "NONE"} | +------------+------------+------------------+------------------+-------------------------------------------------------------------+
Validar a utilização do índice vetorial
As informações sobre a utilização do índice vetorial estão disponíveis nos metadados da tarefa que executou a consulta de pesquisa vetorial. Pode ver os metadados das tarefas através da consola, da ferramenta de linha de comandos bq, da API BigQuery ou das bibliotecas de cliente. Trusted Cloud
Quando usa a Trusted Cloud consola, pode encontrar informações de utilização do índice vetorial nos campos Modo de utilização do índice vetorial e Motivos de não utilização do índice vetorial.
Quando usa a ferramenta bq ou a API BigQuery, pode encontrar informações de utilização do índice de vetores na secção VectorSearchStatistics
do recurso Job
.
O modo de utilização do índice indica se foi usado um índice vetorial, fornecendo um dos seguintes valores:
UNUSED
: não foi usado nenhum índice vetorial.PARTIALLY_USED
: algumas funçõesVECTOR_SEARCH
na consulta usaram índices de vetores e outras não.FULLY_USED
: Todas as funçõesVECTOR_SEARCH
na consulta usaram um índice vetorial.
Quando o valor do modo de utilização do índice é UNUSED
ou PARTIALLY_USED
,
os motivos de não utilização do índice indicam por que motivo os índices de vetores não foram usados na consulta.
Por exemplo, os seguintes resultados devolvidos por
bq show --format=prettyjson -j my_job_id
mostram que o índice não foi usado
porque a opção use_brute_force
foi especificada na função VECTOR_SEARCH
:
"vectorSearchStatistics": { "indexUnusedReasons": [ { "baseTable": { "datasetId": "my_dataset", "projectId": "my_project", "tableId": "my_table" }, "code": "INDEX_SUPPRESSED_BY_FUNCTION_OPTION", "message": "No vector index was used for the base table `my_project:my_dataset.my_table` because use_brute_force option has been specified." } ], "indexUsageMode": "UNUSED" }
Opções de gestão de índices
Para criar índices e fazer com que o BigQuery os mantenha, tem duas opções:
- Use o conjunto de slots partilhados predefinido: quando os dados que planeia indexar estão abaixo do seu limite por organização, pode usar o conjunto de slots partilhados gratuito para a gestão do índice.
- Use a sua própria reserva: para alcançar um progresso de indexação mais previsível e consistente nas suas cargas de trabalho de produção maiores, pode usar as suas próprias reservas para a gestão de índices.
Use espaços partilhados
Se não tiver configurado o seu projeto para usar uma reserva dedicada para indexação, a gestão de índices é processada no conjunto de slots partilhados gratuito, sujeita às seguintes restrições.
Se adicionar dados a uma tabela que façam com que o tamanho total das tabelas indexadas exceda o limite da sua organização, o BigQuery pausa a gestão de índices para essa tabela. Quando isto acontece, o campo index_status
na vista INFORMATION_SCHEMA.VECTOR_INDEXES
apresenta PENDING DISABLEMENT
e o índice é colocado em fila para eliminação. Enquanto o índice estiver pendente de desativação, continua a ser usado em consultas, e é-lhe cobrado o armazenamento do índice.
Após a eliminação do índice, o campo index_status
mostra o índice como TEMPORARILY DISABLED
. Neste estado, as consultas não usam o índice e não lhe é cobrado o armazenamento do índice. Neste caso, o código
IndexUnusedReason
é BASE_TABLE_TOO_LARGE
.
Se eliminar dados da tabela e o tamanho total das tabelas indexadas ficar abaixo do limite por organização, a gestão de índices é retomada. Se o campo index_status
na vista INFORMATION_SCHEMA.VECTOR_INDEXES
for ACTIVE
, as consultas podem usar o índice e é-lhe cobrado o armazenamento do índice.
Pode usar a vista INFORMATION_SCHEMA.SEARCH_INDEXES_BY_ORGANIZATION
para compreender o seu consumo atual em relação ao limite por organização numa determinada região, discriminado por projetos e tabelas.
O BigQuery não oferece garantias sobre a capacidade disponível do conjunto partilhado nem sobre o débito de indexação que vê. Para aplicações de produção, recomendamos que use ranhuras dedicadas para o processamento do índice.
Use a sua própria reserva
Em vez de usar o conjunto de intervalos partilhados predefinido, pode designar opcionalmente a sua própria reserva para indexar as tabelas. A utilização da sua própria reserva garante um desempenho previsível e consistente das tarefas de gestão de índices, como a criação, a atualização e as otimizações em segundo plano.
- Não existem limites de tamanho da tabela quando uma tarefa de indexação é executada na sua reserva.
- A utilização da sua própria reserva dá-lhe flexibilidade na gestão do índice. Se precisar de criar um índice muito grande ou fazer uma atualização importante a uma tabela indexada, pode adicionar temporariamente mais espaços à atribuição.
Para indexar as tabelas num projeto com uma reserva designada,
crie uma reserva
na região onde as tabelas estão localizadas. Em seguida, atribua o projeto à reserva com o valor job_type
definido como BACKGROUND
:
SQL
Use a
CREATE ASSIGNMENT
declaração DDL.
Na Trusted Cloud consola, aceda à página BigQuery.
No editor de consultas, introduza a seguinte declaração:
CREATE ASSIGNMENT `ADMIN_PROJECT_ID.region-LOCATION.RESERVATION_NAME.ASSIGNMENT_ID` OPTIONS ( assignee = 'projects/PROJECT_ID', job_type = 'BACKGROUND');
Substitua o seguinte:
ADMIN_PROJECT_ID
: o ID do projeto do projeto de administração que detém o recurso de reservaLOCATION
: a localização da reservaRESERVATION_NAME
: o nome da reservaASSIGNMENT_ID
: o ID da atribuiçãoO ID tem de ser exclusivo do projeto e da localização, começar e terminar com uma letra minúscula ou um número, e conter apenas letras minúsculas, números e traços.
PROJECT_ID
: o ID do projeto que contém as tabelas a indexar. Este projeto está atribuído à reserva.
Clique em
Executar.
Para mais informações sobre como executar consultas, consulte o artigo Execute uma consulta interativa.
bq
Use o comando bq mk
:
bq mk \ --project_id=ADMIN_PROJECT_ID \ --location=LOCATION \ --reservation_assignment \ --reservation_id=RESERVATION_NAME \ --assignee_id=PROJECT_ID \ --job_type=BACKGROUND \ --assignee_type=PROJECT
Substitua o seguinte:
ADMIN_PROJECT_ID
: o ID do projeto do projeto de administração que detém o recurso de reservaLOCATION
: a localização da reservaRESERVATION_NAME
: o nome da reservaPROJECT_ID
: o ID do projeto a atribuir a esta reserva
Veja as suas tarefas de indexação
É criado um novo trabalho de indexação sempre que um índice é criado ou atualizado numa única tabela. Para ver informações sobre a tarefa, consulte as
vistas INFORMATION_SCHEMA.JOBS*
. Pode filtrar tarefas de indexação definindo job_type IS NULL AND SEARCH(job_id, '`search_index`')
na cláusula WHERE
da sua consulta. O exemplo seguinte apresenta os cinco trabalhos de indexação mais recentes no projeto my_project
:
SELECT * FROM region-us.INFORMATION_SCHEMA.JOBS WHERE project_id = 'my_project' AND job_type IS NULL AND SEARCH(job_id, '`search_index`') ORDER BY creation_time DESC LIMIT 5;
Escolha o tamanho da reserva
Para escolher o número certo de vagas para a sua reserva, deve considerar quando os trabalhos de gestão de índices são executados, quantas vagas usam e como é a sua utilização ao longo do tempo. O BigQuery aciona uma tarefa de gestão de índices nas seguintes situações:
- Cria um índice numa tabela.
- Os dados são modificados numa tabela indexada.
- O esquema de uma tabela muda e isto afeta as colunas que são indexadas.
- Os dados e os metadados do índice são otimizados ou atualizados periodicamente.
O número de ranhuras necessárias para uma tarefa de gestão de índices numa tabela depende dos seguintes fatores:
- O tamanho da tabela
- A taxa de carregamento de dados para a tabela
- A taxa de instruções DML aplicadas à tabela
- O atraso aceitável para criar e manter o índice
- A complexidade do índice, normalmente determinada pelos atributos dos dados, como o número de termos duplicados
Monitorize a utilização e o progresso
A melhor forma de avaliar o número de espaços que precisa para executar eficientemente as suas tarefas de gestão de índices é monitorizar a utilização de espaços e ajustar o tamanho da reserva em conformidade. A seguinte consulta produz a utilização diária de slots
para tarefas de gestão de índices. Apenas os últimos 30 dias estão incluídos na
região us-west1
:
SELECT TIMESTAMP_TRUNC(job.creation_time, DAY) AS usage_date, -- Aggregate total_slots_ms used for index-management jobs in a day and divide -- by the number of milliseconds in a day. This value is most accurate for -- days with consistent slot usage. SAFE_DIVIDE(SUM(job.total_slot_ms), (1000 * 60 * 60 * 24)) AS average_daily_slot_usage FROM `region-us-west1`.INFORMATION_SCHEMA.JOBS job WHERE project_id = 'my_project' AND job_type IS NULL AND SEARCH(job_id, '`search_index`') GROUP BY usage_date ORDER BY usage_date DESC limit 30;
Quando existem slots insuficientes para executar tarefas de gestão de índices, um índice pode ficar dessincronizado com a respetiva tabela e as tarefas de indexação podem falhar. Neste caso, o BigQuery recompila o índice de raiz. Para evitar ter um índice dessincronizado, certifique-se de que tem slots suficientes para suportar as atualizações do índice a partir do carregamento e da otimização de dados. Para mais informações sobre a monitorização da utilização de faixas, consulte os gráficos de recursos de administrador.
Reconstrua um índice vetorial
Quando os dados da tabela mudam significativamente após a criação de um índice vetorial, o índice vetorial pode tornar-se menos eficiente. Quando um índice vetorial é menos eficiente, uma consulta de pesquisa vetorial que inicialmente tinha uma relembrança elevada quando usava o índice tem uma relembrança inferior, porque a mudança na distribuição de dados na tabela base não está representada no índice vetorial.
Se quiser melhorar a capacidade de memorização sem aumentar a latência das consultas de pesquisa, recompile o índice de vetores. Em alternativa, pode aumentar o valor da opção fraction_lists_to_search
de pesquisa de vetores para melhorar a capacidade de memorização, mas isto normalmente torna a consulta de pesquisa mais lenta.
Pode usar a função VECTOR_INDEX.STATISTICS
para calcular a variação dos dados de uma tabela indexada entre o momento em que foi criado um índice de vetores e o presente. Se os dados da tabela tiverem sido alterados o suficiente para exigir uma recompilação do índice de vetores, pode usar a declaração ALTER VECTOR INDEX REBUILD
para recompilar o índice de vetores.
Siga estes passos para reconstruir um índice vetorial:
Aceda à página do BigQuery.
No editor de consultas, execute a seguinte declaração SQL para verificar a variação dos dados da tabela indexada:
SELECT * FROM VECTOR_INDEX.STATISTICS(TABLE DATASET_NAME.TABLE_NAME);
Substitua o seguinte:
DATASET_NAME
: o nome do conjunto de dados que contém a tabela indexada.TABLE_NAME
: o nome da tabela que contém o índice vetorial.
A função devolve um valor
FLOAT64
no intervalo[0,1)
. Um valor mais baixo indica um desvio menor. Normalmente, um valor de0.3
ou superior é considerado uma alteração suficientemente significativa para indicar que uma recompilação do índice vetorial pode ser benéfica.Se a função
VECTOR_INDEX.STATISTICS
indicar que a variação dos dados da tabela é significativa, execute a seguinte declaração SQL para reconstruir o índice vetorial:ALTER VECTOR INDEX IF EXISTS INDEX_NAME ON DATASET_NAME.TABLE_NAME REBUILD;
Substitua o seguinte:
INDEX_NAME
: o nome do índice vetorial que está a reconstruir.DATASET_NAME
: o nome do conjunto de dados que contém a tabela indexada.TABLE_NAME
: o nome da tabela que contém o índice vetorial.
Elimine um índice vetorial
Quando já não precisar de um índice vetorial ou quiser alterar a coluna indexada numa tabela, pode eliminar o índice nessa tabela através da declaração DDL DROP VECTOR INDEX
:
Aceda à página do BigQuery.
No editor de consultas, execute a seguinte declaração SQL:
DROP VECTOR INDEX INDEX_NAME ON DATASET_NAME.TABLE_NAME;
Substitua o seguinte:
INDEX_NAME
: o nome do índice vetorial que está a eliminar.DATASET_NAME
: o nome do conjunto de dados que contém a tabela indexada.TABLE_NAME
: o nome da tabela que contém o índice vetorial.
Se uma tabela indexada for eliminada, o respetivo índice é eliminado automaticamente.
Exporte incorporações para o Vertex AI Vector Search
Para ativar aplicações online de latência ultrabaixa, use a integração do BigQuery com a pesquisa vetorial da Vertex AI para importar as suas incorporações do BigQuery para a pesquisa vetorial e implementar pontos finais de baixa latência. Para mais informações, consulte o artigo Importe dados de índice do BigQuery.
O que se segue?
- Para uma vista geral dos exemplos de utilização, preços e limitações do índice vetorial, consulte a Introdução à pesquisa vetorial.
- Saiba como realizar uma pesquisa vetorial usando a função
VECTOR_SEARCH
. - Saiba mais acerca do
CREATE VECTOR INDEX
extrato. - Experimente o tutorial Incorporações de pesquisa com pesquisa vetorial.