Visão geral sobre a pesquisa vetorial - Amazon ElastiCache

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Visão geral sobre a pesquisa vetorial

ElastiCache for Valkey fornece recursos para indexar, pesquisar e atualizar bilhões de incorporações vetoriais de alta dimensão. A pesquisa vetorial permite criar, manter e usar índices secundários para uma pesquisa eficiente e escalável. Cada operação de pesquisa vetorial se aplica a um único índice. As operações de índice se aplicam somente ao índice especificado. Qualquer número de operações pode ser emitido contra qualquer índice a qualquer momento, com exceção das operações de criação e exclusão de índices. No nível do cluster, várias operações em vários índices podem estar em andamento simultaneamente.

Neste documento, os termos chave, linha e registro são idênticos e usados de maneira intercambiável. Da mesma forma, os termos coluna, campo, caminho e membro também são usados de maneira intercambiável.

O comando FT.CREATE pode ser usado para criar um índice para um subconjunto de chaves com os tipos de índice especificados. O comando FT.SEARCH realiza consultas nos índices criados e FT.DROPINDEX remove um índice existente e todos os dados associados. Não há comandos especiais para adicionar, excluir ou modificar dados indexados. Os comandos HASH ou JSON existentes que modificam uma chave em um índice atualizam automaticamente esse índice.

Índices e o espaço de chaves do Valkey OSS

Índices são construídos e mantidos em um subconjunto do espaço de chaves do Valkey OSS. O espaço de chaves para cada índice é definido por uma lista de prefixos de chave que são fornecidos quando esse índice é criado. A lista de prefixos é opcional e, se omitida, todo o espaço de chaves fará parte desse índice. Vários índices podem escolher subconjuntos separados ou sobrepostos do espaço de chaves, sem limitação.

Os índices também são digitados, pois cobrem apenas as chaves que têm um tipo correspondente. Atualmente, apenas há suporte para índices dos tipos JSON e HASH. Um índice HASH indexa somente as chaves HASH cobertas por sua lista de prefixos e, da mesma maneira, um índice JSON indexa somente as chaves JSON cobertas por sua lista de prefixos. As chaves na lista de prefixos do espaço de chaves de um índice que não têm o tipo designado são ignoradas e não afetam as operações de pesquisa.

Um índice é atualizado quando um comando modifica qualquer chave que está dentro de um espaço de chaves de um índice. O Valkey extrai automaticamente os campos declarados para cada índice e atualiza o índice com o novo valor. O processo de atualização tem três etapas. Na primeira etapa, a chave HASH ou JSON é modificada e o cliente solicitante é bloqueado. A segunda etapa é executada em segundo plano e atualiza cada um dos índices que contêm a chave modificada. Na terceira etapa, o cliente é desbloqueado. Assim, para operações de consulta realizadas na mesma conexão de uma mutação, essa alteração é imediatamente visível nos resultados da pesquisa.

A criação de um índice é um processo em várias etapas. A primeira delas é executar o comando FT.CREATE, que define o índice. A execução bem-sucedida de uma criação inicia automaticamente a segunda etapa: o preenchimento. O processo de preenchimento é executado em um thread em segundo plano e verifica o espaço de chaves em busca de chaves que estejam na lista de prefixos do novo índice. Cada chave encontrada é adicionada ao índice. Por fim, todo o espaço de chaves é verificado, concluindo o processo de criação do índice. Enquanto o processo de preenchimento está em execução, são permitidas mutações das chaves indexadas, não há restrições, e o processo de preenchimento do índice não será concluído até que todas as chaves estejam devidamente indexadas. Tentativas de operações de consulta feitas enquanto um índice está sendo preenchido não são permitidas e serão encerradas com um erro. O comando FT.INFO retorna o status do processo de preenchimento no campo 'backfill_status'.

Tipos de campos de índice

Cada índice tem um tipo específico que é declarado quando esse índice é criado junto com um local de um campo (coluna) para ser indexado. Para chaves HASH, a localização é o nome do campo dentro do HASH. Para chaves JSON, a localização é uma descrição do caminho do JSON. Quando uma chave é modificada, os dados associados aos campos declarados são extraídos, convertidos no tipo declarado e armazenados no índice. Se os dados estiverem ausentes ou não puderem ser convertidos com êxito no tipo declarado, esse campo será omitido do índice. Há três tipos de campos, conforme explicado a seguir:

  • Campos vetoriais contêm um vetor de números, também conhecido como incorporação de vetores. Os campos vetoriais podem ser usados para filtrar vetores com base em métricas de distância especificadas que medem a similaridade. No caso de índices HASH, o campo deve conter todo o vetor codificado em formato binário (little-endian IEEE 754). No caso de chaves JSON, o caminho deve fazer referência a uma matriz do tamanho correto preenchida com números. Quando uma matriz JSON é usada como um campo vetorial, a representação interna dessa matriz na chave JSON é convertida no formato exigido pelo algoritmo selecionado, reduzindo o consumo e a precisão da memória. Operações de leitura subsequentes usando os comandos JSON produzirão o valor de precisão reduzido.

  • Campos numéricos contêm um único número. Campos numéricos podem ser usados com o operador de pesquisa de intervalo. Para HASH, espera-se que o campo contenha o texto ASCII de um número escrito no formato padrão para números fixos ou de pontos flutuantes. Para campos JSON, devem ser seguidas as regras numéricas de números JSON. Independentemente da representação na chave, esse campo é convertido em um número de pontos flutuantes de 64 bits para armazenamento no índice. Como os números subjacentes são armazenados em ponto flutuante com suas limitações de precisão, as regras comuns sobre comparações numéricas para números de pontos flutuantes são aplicáveis.

  • Campos de etiqueta contêm zero ou mais valores de etiqueta codificados como uma única string UTF-8. Campos de etiquetas podem ser usados para filtrar consultas de equivalência de valores de etiquetas com comparação com ou sem distinção entre maiúsculas e minúsculas. A string é analisada em valores de etiquetas usando um caractere separador (o padrão é uma vírgula, mas pode ser substituído) com espaços em branco à esquerda e à direita removidos. Qualquer número de valores de etiquetas pode estar contido em um único campo de etiqueta.

Algoritmos de índice vetorial

Dois algoritmos de índice vetorial são compatíveis no Valkey:

  • Flat: o algoritmo Flat é um processamento linear por força bruta de cada vetor no índice, produzindo respostas exatas dentro dos limites da precisão dos cálculos de distância. Devido ao processamento linear do índice, os tempos de execução desse algoritmo podem ser muito altos para índices grandes. Índices planos são compatíveis com velocidades de ingestão mais altas.

  • HNSW (Hierarchical Navigable Small Worlds): o algoritmo HNSW é uma alternativa que fornece uma aproximação da resposta mais próxima em troca de tempos de execução substancialmente menores. O algoritmo é controlado por três parâmetros: M, EF_CONSTRUCTION e EF_RUNTIME. Os dois primeiros parâmetros são especificados no momento da criação do índice e não podem ser alterados. O parâmetro EF_RUNTIME tem um valor padrão que é especificado no momento da criação do índice, mas pode ser substituído mais tarde em qualquer operação de consulta individual. Esses três parâmetros interagem para equilibrar o consumo de memória e CPU durante operações de ingestão e consulta, bem como para controlar a qualidade da aproximação de uma pesquisa KNN exata (conhecida como taxa de recall).

No HNSW, o parâmetro M controla o número máximo de vizinhos aos quais cada nó pode se conectar, moldando a densidade do índice. Um M maior, como 32 e superior, produz um gráfico mais conectado, melhorando a velocidade de recuperação e consulta porque existem mais caminhos para alcançar vizinhos relevantes. No entanto, ele aumenta o tamanho do índice, o uso da memória e retarda a indexação. Um M menor, como 8 ou menos, gera um faster-to-build índice menor com menor uso de memória, mas o recall diminui e as consultas podem demorar mais devido ao menor número de conexões.

O parâmetro EF_construction determina quantas conexões candidatas são avaliadas ao criar o índice. Um EF_construction mais alto, como 400 e superior, significa que o indexador considera mais caminhos antes de selecionar vizinhos, resultando em um gráfico que melhora a eficiência da recuperação e da consulta posteriormente, mas ao custo de uma indexação mais lenta e maior uso de CPU e memória durante a construção. Um EF_construction baixo, como 64-120, acelera a indexação e reduz o uso de recursos, mas o gráfico resultante pode reduzir a recuperação e retardar as consultas, mesmo se o EF_runtime estiver definido como alto.

Por fim, o EF_runtime controla a amplitude da pesquisa durante a consulta, controlando quantos vizinhos candidatos são explorados em tempo de execução. Defini-la como alta aumenta a recuperação e a precisão, mas às custas da latência da consulta e do uso da CPU. Um EF_runtime baixo torna as consultas mais rápidas e leves, mas com recuperação reduzida. Ao contrário de M ou EF_construction, esse parâmetro não afeta o tamanho do índice ou o tempo de construção, tornando-o o parâmetro para ajustar as compensações de recuperação versus latência após a criação de um índice.

Ambos os algoritmos de pesquisa vetorial (Flat e HNSW) aceitam um parâmetro opcional INITIAL_CAP. Quando especificado, esse parâmetro pré-aloca memória para os índices, resultando na redução da sobrecarga de gerenciamento de memória e no aumento das taxas de ingestão de vetores. Índices planos oferecem melhores velocidades de ingestão do que o HNSW.

Algoritmos de pesquisa vetorial, como o HNSW, podem não lidar de maneira eficiente com a exclusão ou substituição de vetores inseridos anteriormente. O uso dessas operações pode resultar em consumo excessivo de memória de índice, and/or degradando a qualidade de recall. A reindexação é um método para restaurar a recuperação ideal do uso da memória. and/or

Segurança da pesquisa vetorial

Os mecanismos de segurança de Valkey ACL (listas de controle de acesso) para acesso a comandos e dados são estendidos para controlar o recurso de pesquisa. Há suporte total para o controle de ACL de comandos de pesquisa individuais. É fornecida uma nova categoria de ACL, @search, e muitas das categorias existentes (@fast, @read, @write etc.) são atualizadas para incluir os novos comandos. Os comandos de pesquisa não modificam os dados de chaves, o que significa que o mecanismo de ACL existente para acesso de gravação é preservado. As regras de acesso para operações HASH e JSON não são modificadas pela presença de um índice. O controle normal de acesso em nível de chave ainda é aplicado a esses comandos.

Comandos de pesquisa com um índice também têm o acesso controlado por meio da ACL. Verificações de acesso são realizadas no nível do índice inteiro, e não no nível por chave. Isso significa que o acesso a um índice será concedido a um usuário somente se este tiver permissão para acessar todas as chaves possíveis na lista de prefixos do espaço de chaves desse índice. Em outras palavras, o conteúdo real de um índice não controla o acesso. Pelo contrário, é o conteúdo teórico de um índice, conforme definido pela lista de prefixos, que é usado para a verificação de segurança. Situações em que um usuário tem acesso de leitura e and/or gravação a uma chave, mas não consegue acessar um índice contendo essa chave, são possíveis. Observe que somente o acesso para leitura ao espaço de chaves é necessário para criar ou usar um índice: a presença ou ausência do acesso para gravação não é levada em consideração.