Gerenciar índices vetoriais
Neste documento, descrevemos como criar e gerenciar índices vetoriais para acelerar suas pesquisas de vetores.
Um índice vetorial é uma estrutura de dados projetada para permitir que a
função VECTOR_SEARCH
seja executada com mais eficiência, especialmente em grandes conjuntos de dados.
Ao usar um índice, VECTOR_SEARCH
usa algoritmos
Vizinho aproximado mais próximo (ANN, na sigla em inglês)
para reduzir a latência da consulta e o custo computacional. Embora a ANN apresente
um grau de aproximação, o que significa que a
recordação
pode não ser de 100%, as melhorias de desempenho geralmente oferecem uma vantagem
para a maioria das aplicações.
Papéis e permissões
Para criar um índice vetorial, é necessário ter a permissão bigquery.tables.createIndex
do IAM na tabela em que você está criando o índice. Para remover um índice vetorial, é necessário ter a permissão bigquery.tables.deleteIndex
. Cada um dos papéis do IAM predefinidos a seguir inclui as permissões necessárias para trabalhar com índices vetoriais:
- Proprietário de dados do BigQuery (
roles/bigquery.dataOwner
) - Editor de dados do BigQuery (
roles/bigquery.dataEditor
)
Escolher um tipo de índice vetorial
O BigQuery oferece dois tipos de índices de vetores, IVF e
TreeAH, cada um com suporte a
diferentes casos de uso. O BigQuery oferece suporte a lotes para pesquisa
vetorial processando várias linhas dos dados de entrada na
função VECTOR_SEARCH
.
Para pequenos lotes de consultas, os índices IVF são preferidos. Para grandes lotes de consultas,
os índices TreeAH, que são criados com o algoritmo ScaNN do Google,
são preferidos.
Índice de IVF
O IVF é um índice de arquivo invertido, que usa um algoritmo k-means para agrupar os dados vetoriais e, em seguida, particiona esses dados com base nesses clusters. A
função VECTOR_SEARCH
pode usar essas partições para reduzir a quantidade de dados que precisa ler a fim de
determinar um resultado.
Índice TreeAH
O tipo de índice TreeAH é nomeado pela combinação de uma estrutura semelhante a uma árvore e o uso de hash assimétrico (AH), uma técnica de quantização do algoritmo ScaNN. Um índice TreeAH funciona da seguinte maneira:
- A tabela base é dividida em fragmentos menores e mais fáceis de gerenciar.
- Um modelo de agrupamento é treinado, com o número de clusters derivados da
opção
leaf_node_embedding_count
no argumentotree_ah_options
da instruçãoCREATE VECTOR INDEX
. - Os vetores são compactados com a quantização do produto, uma técnica que reduz o uso de memória. Os vetores compactados são armazenados nas tabelas de índice em vez dos vetores originais, reduzindo os tamanhos dos índices de vetores.
- Quando a função
VECTOR_SEARCH
é executada, uma lista de candidatos para cada vetor de consulta é computada de maneira eficiente usando hash assimétrico, que é otimizado por hardware para cálculos de distância aproximada. Esses candidatos são reavaliados e classificados usando embeddings exatas.
O algoritmo TreeAH é otimizado para consultas em lote que processam centenas ou mais vetores de consulta. O uso 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 da sobrecarga, o algoritmo IVF pode ser melhor quando você tem um número menor de vetores de consulta.
Sugerimos que você teste o tipo de índice TreeAH se o caso de uso atender aos seguintes critérios:
Sua tabela tem até 200 milhões de linhas.
Você executa com frequência consultas em lote grandes que envolvem centenas ou mais vetores de consulta.
Para pequenas consultas em lote com o tipo de índice TreeAH, o VECTOR_SEARCH
pode
retornar à
pesquisa de força bruta.
Quando isso ocorre, um
IndexUnusedReason
é fornecido para explicar por que o índice vetorial não foi utilizado.
Criar um índice vetorial IVF
Para criar um índice vetorial de FIV, use a
instrução de linguagem de definição de dados (DDL)
CREATE VECTOR INDEX
:
Acessar a página do BigQuery.
No editor de consultas, execute a seguinte instruçã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:
INDEX_NAME
: o nome do índice vetorial que você está criando. Como o índice é sempre criado no mesmo projeto e conjunto de dados da 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 embeddings.COLUMN_NAME
: o nome de uma coluna que contém os dados de embeddings. A coluna precisa ter um tipo deARRAY<FLOAT64>
. A coluna não pode ter campos filhos. Todos os elementos na matriz precisam ser diferentes deNULL
, e todos os valores na coluna precisam ter as mesmas dimensões da matriz.STORED_COLUMN_NAME
: o nome de uma coluna de nível superior na tabela a ser armazenada no índice de vetor. O tipo de coluna não pode serRANGE
. As colunas armazenadas não serão usadas se a tabela tiver uma política de acesso no nível da linha ou se a coluna tiver uma tag de política. Para informações sobre como ativar colunas armazenadas, consulte Armazenar colunas e pré-filtrar.DISTANCE_TYPE
: especifica o tipo de distância padrão a ser usado na pesquisa de vetor com esse índice. Os valores compatíveis sãoEUCLIDEAN
,COSINE
eDOT_PRODUCT
. O padrão éEUCLIDEAN
.A criação do índice sempre usa a distância
EUCLIDEAN
para o treinamento, mas a distância usada na funçãoVECTOR_SEARCH
pode ser diferente.Se você especificar um valor para o argumento
distance_type
da funçãoVECTOR_SEARCH
, esse valor será usado no lugar deDISTANCE_TYPE
.NUM_LISTS
: um valorINT64
que especifica o número de listas em que o índice de IVF agrupa e particiona seus dados de vetor. Esse valor precisa ser 5.000 ou menor. Durante a indexação, os vetores são atribuídos à lista correspondente ao centroide do cluster mais próximo. Se você omitir esse argumento, o BigQuery vai determinar um valor padrão com base nas características dos seus dados. O valor padrão funciona bem para a maioria dos casos de uso.NUM_LISTS
controla a granularidade do ajuste de consulta. Valores mais altos criam mais listas, então você pode definir a opçãofraction_lists_to_search
da funçãoVECTOR_SEARCH
para verificar uma porcentagem menor do índice. Por exemplo, a verificação de 1% de 100 listas em vez de 10% de 10 listas. Isso permite um controle mais preciso da velocidade e da recuperação da pesquisa, mas aumenta um pouco o custo de indexação. Defina esse valor de argumento com base na precisão necessária para ajustar o escopo da consulta.
O exemplo a seguir 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 a seguir cria um índice vetorial na coluna embedding
de my_table
e especifica o tipo de distância a ser usado 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}')
Criar um índice vetorial TreeAH
Para criar um índice de vetor TreeAH, use a instrução de linguagem de definição de dados (DDL)
CREATE VECTOR INDEX
:
Acessar a página do BigQuery.
No editor de consultas, execute a seguinte instruçã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:
INDEX_NAME
: o nome do índice vetorial que você está criando. Como o índice é sempre criado no mesmo projeto e conjunto de dados da 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 embeddings.COLUMN_NAME
: o nome de uma coluna que contém os dados de embeddings. A coluna precisa ter um tipo deARRAY<FLOAT64>
. A coluna não pode ter campos filhos. Todos os elementos na matriz precisam ser diferentes deNULL
, e todos os valores na coluna precisam ter as mesmas dimensões da matriz.STORED_COLUMN_NAME
: o nome de uma coluna de nível superior na tabela a ser armazenada no índice de vetor. O tipo de coluna não pode serRANGE
. As colunas armazenadas não serão usadas se a tabela tiver uma política de acesso no nível da linha ou se a coluna tiver uma tag de política. Para informações sobre como ativar colunas armazenadas, consulte Armazenar colunas e pré-filtrar.DISTANCE_TYPE
: um argumento opcional que especifica o tipo de distância padrão a ser usado na pesquisa de vetor com esse índice. Os valores compatíveis sãoEUCLIDEAN
,COSINE
eDOT_PRODUCT
. O padrão éEUCLIDEAN
.A criação do índice sempre usa a distância
EUCLIDEAN
para o treinamento, mas a distância usada na funçãoVECTOR_SEARCH
pode ser diferente.Se você especificar um valor para o argumento
distance_type
da funçãoVECTOR_SEARCH
, esse valor será usado no lugar deDISTANCE_TYPE
.LEAF_NODE_EMBEDDING_COUNT
: um valor deINT64
maior ou igual a 500 que especifica o número aproximado de vetores em cada nó de folha da árvore criada pelo algoritmo TreeAH. O algoritmo TreeAH divide todo o espaço de dados em várias listas, e cada lista contém aproximadamenteLEAF_NODE_EMBEDDING_COUNT
pontos de dados. Um valor mais baixo cria mais listas com menos pontos de dados, enquanto um valor maior cria menos listas com mais pontos de dados. O padrão é 1.000, que é adequado para a maioria dos conjuntos de dados.NORMALIZATION_TYPE
: um valorSTRING
. Os valores aceitos sãoNONE
ouL2
. O padrão éNONE
. A normalização acontece antes de qualquer processamento, para os dados da tabela base e da consulta, mas não modifica a coluna de embeddingCOLUMN_NAME
emTABLE_NAME
. Dependendo do conjunto de dados, do modelo de embedding e do tipo de distância usado durante aVECTOR_SEARCH
, a normalização dos embeddings pode melhorar a recuperação.
O exemplo a seguir cria um índice vetorial na coluna embedding
de my_table
e especifica o tipo de distância a ser usado e as opções de 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"}');
Armazenar colunas e pré-filtrar
Para melhorar ainda mais a eficiência do seu índice de vetor, especifique colunas da sua tabela base para armazenar no índice de vetor. O uso de colunas armazenadas pode otimizar consultas que chamam a função VECTOR_SEARCH
das seguintes maneiras:
Em vez de pesquisar uma tabela inteira, você pode chamar a função
VECTOR_SEARCH
em uma instrução de consulta que pré-filtre a tabela base com uma cláusulaWHERE
. Se a tabela tiver um índice e você filtrar apenas as colunas armazenadas, o BigQuery otimizará a consulta filtrando os dados antes da pesquisa e usando o índice para pesquisar o conjunto de resultados menor. Se você filtrar colunas que não são armazenadas, o BigQuery aplicará o filtro após a pesquisa da tabela ou pós-filtros.A função
VECTOR_SEARCH
gera uma estrutura chamadabase
que contém todas as colunas da tabela base. Sem colunas armazenadas, uma mesclagem potencialmente cara é necessária para recuperar as colunas armazenadas embase
. Se você usar um índice IVF e a consulta selecionar apenas colunas armazenadas debase
, o BigQuery otimizará a consulta para eliminar essa junção. Para índices TreeAH, a mesclagem com a tabela base não é removida. As colunas armazenadas em índices TreeAH são usadas apenas para pré-filtragem.
Para armazenar colunas, liste-as na cláusula STORING
da
instrução DDL CREATE VECTOR INDEX
.
Armazenar colunas aumenta o tamanho do índice vetorial. Por isso, é melhor armazenar apenas as colunas mais usadas ou filtradas.
O exemplo a seguir cria um índice vetorial com colunas armazenadas e 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);
Pré-filtros e pós-filtros
Nas operações VECTOR_SEARCH
do BigQuery, a pré-filtragem e a
pós-filtragem servem para refinar os resultados da pesquisa, aplicando condições com base nas
colunas de metadados associadas às embeddings de vetor. É importante
entender as diferenças, a implementação e o impacto delas para otimizar
a performance, o custo e a precisão da consulta.
A pré-filtragem e a pós-filtragem são definidas da seguinte maneira:
- Pré-filtragem:aplica condições de filtro antes que a pesquisa de vizinho mais próximo aproximado (ANN) realize cálculos de distância em vetores candidatos. Isso restringe o conjunto de vetores que são considerados durante a pesquisa. Consequentemente, a pré-filtragem geralmente resulta em tempos de consulta mais rápidos e custos computacionais reduzidos, já que a pesquisa de ANN avalia menos candidatos em potencial.
- Pós-filtragem:aplica condições de filtro depois que os vizinhos mais próximos
top_k
iniciais são identificados pela pesquisa de ANN. Isso refina o conjunto de resultados final com base nos critérios especificados.
A posição 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 precisa ser aplicada ao argumento de tabela base da função VECTOR_SEARCH
.
O predicado precisa ser aplicado a uma coluna armazenada. Caso contrário, ele se torna um pós-filtro.
O exemplo a seguir 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 pós-filtro, a cláusula WHERE
da consulta precisa ser aplicada fora
da função VECTOR_SEARCH
para filtrar os resultados retornados pela
pesquisa.
O exemplo a seguir mostra como criar um pós-filtro:
-- 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 você usa a pós-filtragem ou quando a tabela base filtra as colunas não armazenadas especificadas e, portanto, atua como pós-filtros, o conjunto de resultados finais pode conter menos de top_k
linhas, possivelmente até mesmo nenhuma, se o predicado for seletivo. Se você precisar de um número específico de resultados
após a filtragem, considere especificar um valor de top_k
maior ou aumentar o
valor de fraction_lists_to_search
na chamada VECTOR_SEARCH
.
Em alguns casos, principalmente se o pré-filtro for muito seletivo, a pré-filtragem
também pode reduzir o tamanho do conjunto de resultados. Se isso acontecer, tente aumentar o
valor de fraction_lists_to_search
na chamada VECTOR_SEARCH
.
Limitações
- Não é possível usar visualizações lógicas no seu pré-filtro.
- Se o pré-filtro tiver uma subconsulta, ela poderá interferir no uso do índice.
- Se o modo, o tipo ou o esquema de uma coluna for alterado na tabela base e se ela for uma coluna armazenada no índice de vetor, poderá haver um atraso até que essa mudança seja refletida no índice de vetor. Até que as atualizações sejam aplicadas ao índice, as consultas de pesquisa de vetor usam as colunas armazenadas modificadas da tabela base.
- Se você selecionar uma coluna do tipo
STRUCT
na saídaquery
de uma consultaVECTOR_SEARCH
em uma tabela que tenha um índice com colunas armazenadas, a consulta inteira poderá falhar.
Como saber quando os dados são indexados
Os índices vetoriais são totalmente gerenciados pelo BigQuery e atualizados automaticamente quando a tabela indexada é alterada.
A indexação é assíncrona. Há um atraso entre a adição de novas linhas à tabela de base e a reflexão dessas linhas no índice. No entanto, a
função VECTOR_SEARCH
ainda considera todas as linhas e não perde
linhas não indexadas. A função pesquisa registros indexados usando o índice e
usa a pesquisa bruta para os registros que ainda não foram indexados.
Se você criar um índice vetorial em uma tabela com menos de 10 MB, ele não será preenchido. Da mesma forma, se você excluir dados de uma tabela indexada e o tamanho dela ficar abaixo de 10 MB, o índice vetorial será desativado temporariamente. Nesse caso, as consultas de pesquisa de vetor não usam o índice, e o
código indexUnusedReasons
na seção
vectorSearchStatistics
do recurso Job
é BASE_TABLE_TOO_SMALL
. Sem o índice, VECTOR_SEARCH
volta automaticamente a usar força bruta para encontrar os vizinhos de embeddings mais perto.
Se você excluir a coluna indexada em uma tabela ou renomear a tabela, o índice vetorial será excluído automaticamente.
Monitorar o status dos índices vetoriais
É possível monitorar a integridade dos índices vetoriais consultando as visualizações INFORMATION_SCHEMA
. As visualizações a seguir contêm metadados sobre índices
vetoriais:
A visualização
INFORMATION_SCHEMA.VECTOR_INDEXES
tem informações sobre os índices vetoriais em um conjunto de dados.Depois que a instrução
CREATE VECTOR INDEX
for concluída, o índice ainda precisará ser preenchido antes de ser usado. É possível usar as colunaslast_refresh_time
ecoverage_percentage
para verificar a prontidão de um índice vetorial. Se o índice vetorial não estiver pronto, ainda será possível usar a funçãoVECTOR_SEARCH
em uma tabela. Talvez ela seja executada mais lentamente sem o índice.A visualização
INFORMATION_SCHEMA.VECTOR_INDEX_COLUMNS
tem informações sobre as colunas indexadas por vetor de todas as tabelas em um conjunto de dados.A visualização
INFORMATION_SCHEMA.VECTOR_INDEX_OPTIONS
tem informações sobre as opções usadas pelos índices vetoriais em um conjunto de dados.
Exemplos de índice vetorial
O exemplo a seguir mostra todos os índices vetoriais ativos das tabelas no conjunto de dados my_dataset
, localizado no projeto my_project
. Isso inclui os nomes, as instruções DDL usadas para criá-los e a porcentagem de cobertura. Se uma tabela base indexada for menor que 10 MB, o índice não será preenchido. Nesse caso, o valor de coverage_percentage
será 0.
SELECT table_name, index_name, ddl, coverage_percentage FROM my_project.my_dataset.INFORMATION_SCHEMA.VECTOR_INDEXES WHERE index_status = 'ACTIVE';
O resultado será 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 consulta a seguir extrai informações de 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 será 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 consulta a seguir extrai informações de opções de índice vetorial:
SELECT table_name, index_name, option_name, option_type, option_value FROM my_project.dataset.INFORMATION_SCHEMA.VECTOR_INDEX_OPTIONS;
O resultado será 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"} | +------------+------------+------------------+------------------+-------------------------------------------------------------------+
Como verificar o uso do índice vetorial
As informações sobre o uso do índice vetorial estão disponíveis nos metadados do job que executou a consulta de pesquisa de vetor. Para acessar os metadados do job, use o Google Cloud console, a ferramenta de linha de comando bq, a API BigQuery ou as bibliotecas de cliente.
Ao usar o console Google Cloud , é possível encontrar informações sobre o uso do índice vetorial nos campos Modo de uso do índice vetorial e Motivos da não utilização do índice vetorial.
Ao usar a ferramenta bq ou a API BigQuery, você encontra informações sobre o uso do índice vetorial na seção VectorSearchStatistics
do recurso Job
.
O modo de uso do índice indica se um índice vetorial foi usado fornecendo um dos seguintes valores:
UNUSED
: nenhum índice vetorial foi usado.PARTIALLY_USED
: algumas funçõesVECTOR_SEARCH
na consulta usaram índices vetoriais e outras não.FULLY_USED
: cada funçãoVECTOR_SEARCH
na consulta usou um índice vetorial.
Quando o valor do modo de uso do índice é UNUSED
ou PARTIALLY_USED
, os motivos da não utilização do índice indicam por que os índices vetoriais não foram usados na consulta.
Por exemplo, os resultados a seguir retornados 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 gerenciamento de índice
Para criar índices vetoriais e fazer o BigQuery mantê-los, há duas opções:
- Use o pool de slots compartilhado padrão: quando os dados que você planeja indexar estiverem abaixo do limite por organização, será possível usar o pool de slots compartilhado para gerenciamento de índices.
- Use sua própria reserva: para atingir um progresso de indexação mais previsível e consistente em cargas de trabalho de produção maiores, use suas próprias reservas para o gerenciamento de índices.
Usar slots compartilhados
Se você não tiver configurado o projeto para usar uma reserva dedicada para indexação, o gerenciamento de índices será processado no pool de slots compartilhado e sem custos financeiros, sujeito às restrições a seguir.
Se você adicionar dados a uma tabela base que faça com que o tamanho total das tabelas
indexadas excedam o limite da sua organização,
o BigQuery pausará o gerenciamento de índice
em todas as tabelas indexadas. Quando isso acontece, o campo index_status
na visualização INFORMATION_SCHEMA.VECTOR_INDEXES
exibe PENDING DISABLEMENT
e o índice é colocado em fila para exclusão. Embora o índice esteja com a desativação pendente, ele ainda é usado nas consultas e há cobrança pelo armazenamento do índice.
Depois que um índice é excluído, o campo index_status
mostra o índice como TEMPORARILY DISABLED
. Nesse estado, as consultas não usam o índice e não há cobrança pelo armazenamento dele. Nesse caso, o
código IndexUnusedReason
é BASE_TABLE_TOO_LARGE
.
Se você excluir os dados da tabela base e o tamanho total das tabelas base indexadas
estiver abaixo do limite por organização, o gerenciamento de índice será retomado para
todas as tabelas base indexadas. O campo index_status
na visualização INFORMATION_SCHEMA.VECTOR_INDEXES
é ACTIVE
, as consultas podem usar o índice e há cobrança pelo armazenamento do índice.
O BigQuery não oferece garantias sobre a capacidade disponível do pool compartilhado ou a capacidade de indexação que você vê. Para aplicativos de produção, convém usar slots dedicados para o processamento de índice.
Usar sua própria reserva
Em vez de usar o pool de slots compartilhado padrão, é possível designar sua própria reserva para indexar as tabelas. Usar sua própria reserva garante um desempenho previsível e consistente de jobs de gerenciamento de índice, como criação, atualização e otimizações em segundo plano.
- Não há limites de tamanho de tabela quando um job de indexação for executado na reserva.
- O uso da sua própria reserva oferece flexibilidade no gerenciamento do índice. Se você precisar criar um índice muito grande ou fazer uma grande atualização para uma tabela indexada, adicione temporariamente mais slots à atribuição.
Para indexar as tabelas em um projeto com uma reserva designada, crie uma reserva na região onde as tabelas base estão localizadas. Em seguida, atribua o projeto à reserva com o job_type
definido como BACKGROUND
:
SQL
Use a
instrução DDL CREATE ASSIGNMENT
.
No console Google Cloud , acesse a página BigQuery.
No editor de consultas, digite a seguinte instrução:
CREATE ASSIGNMENT `ADMIN_PROJECT_ID.region-LOCATION.RESERVATION_NAME.ASSIGNMENT_ID` OPTIONS ( assignee = 'projects/PROJECT_ID', job_type = 'BACKGROUND');
Substitua:
ADMIN_PROJECT_ID
: o ID do projeto de administração que é proprietário do recurso de reserva.LOCATION
: o local da reservaRESERVATION_NAME
: o nome da reservaASSIGNMENT_ID
: o ID da atribuição.Ele precisa ser exclusivo do projeto e do local, 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 serem indexadas. Este projeto está atribuído à reserva.
Clique em
Executar.
Para mais informações sobre como executar consultas, acesse Executar 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:
ADMIN_PROJECT_ID
: o ID do projeto de administração que é proprietário do recurso de reserva.LOCATION
: o local da reservaRESERVATION_NAME
: o nome da reservaPROJECT_ID
: o ID do projeto a ser atribuído a essa reserva.
Veja seus jobs de indexação
Um novo job de indexação é criado sempre que um índice é criado ou atualizado em uma única tabela. Para ver informações sobre o job, consulte as visualizações INFORMATION_SCHEMA.JOBS*
. É possível filtrar por jobs de indexação definindo job_type IS NULL AND SEARCH(job_id, '`search_index`')
na cláusula WHERE
da sua consulta. O exemplo a seguir lista os cinco jobs 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 slots para sua reserva, considere quando os jobs de gerenciamento de índice são executados, quantos slots eles usam e como é o uso ao longo do tempo. O BigQuery aciona um job de gerenciamento de índice nas seguintes situações:
- Você cria um índice em uma tabela.
- Os dados são modificados em uma tabela indexada.
- O esquema de uma tabela muda, e isso afeta as colunas que são indexadas.
- Os dados e metadados do índice são otimizados ou atualizados periodicamente.
O número de slots necessários para um job de gerenciamento de índice em uma tabela depende dos seguintes fatores:
- o tamanho da tabela
- a taxa de ingestão de dados para a tabela
- a taxa de instruções DML aplicadas à tabela
- o atraso aceitável para a criação e manutenção do índice
- A complexidade do índice, normalmente determinada por atributos dos dados, como o número de termos duplicados
Monitore o uso e o progresso
A melhor maneira de avaliar o número de slots necessários para executar com eficiência os jobs de gerenciamento de índice é monitorar a utilização deles e ajustar o tamanho da reserva adequadamente. A consulta a seguir produz o uso diário de slots para jobs de gerenciamento de índice. Somente os últimos 30 dias sã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 não há slots suficientes para executar jobs de gerenciamento de índice, um índice pode ficar dessincronizado com a tabela, e os jobs de indexação poderão falhar. Nesse caso, o BigQuery recria o índice do zero. Para evitar um índice não sincronizado, verifique se você tem slots suficientes para oferecer suporte a atualizações de índice da ingestão e da otimização de dados. Para mais informações sobre o monitoramento do uso do slot, consulte gráficos de recursos de administrador.
Excluir um índice vetorial
Quando você não precisar mais de um índice vetorial ou quiser alterar qual coluna será indexada em uma tabela, exclua o índice dessa tabela usando a instrução DDL DROP VECTOR INDEX
.
Por exemplo:
DROP VECTOR INDEX my_index ON my_dataset.indexed_table;
Se uma tabela indexada for excluída, o índice dela será excluído automaticamente.
A seguir
- Para uma visão geral dos casos de uso, preços e limitações dos índices vetoriais, consulte Introdução à pesquisa de vetor.
- Saiba como realizar uma pesquisa de vetor usando a
função
VECTOR_SEARCH
. - Saiba mais sobre a
instrução
CREATE VECTOR INDEX
. - Siga o tutorial Pesquisar embeddings com a pesquisa de vetor.