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
A pesquisa vetorial baseia-se na criação, na manutenção e no uso de índices. Cada operação de pesquisa vetorial especifica um único índice e está confinada a esse índice, ou seja, as operações em um índice não são afetadas pelas operações em nenhum outro índice. Com exceção das operações para criar e destruir índices, qualquer número de operações pode ser emitido em qualquer índice a qualquer momento, o que significa que, no nível do cluster, várias operações em vários índices podem estar em andamento simultaneamente.
Índices individuais são objetos nomeados que existem em um namespace exclusivo, separado dos outros OSS namespaces do Redis: chaves, funções etc. Cada índice é conceitualmente semelhante a uma tabela de banco de dados convencional, pois está estruturado em duas dimensões: coluna e linhas. Cada linha na tabela corresponde a uma OSS chave Redis. Cada coluna no índice corresponde a um membro ou a uma parte dessa chave. 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 são essencialmente idênticos e também são usados de maneira intercambiável.
Não há comandos especiais para adicionar, excluir ou modificar dados indexados. Em vez disso, os comandos HASH ou JSON existentes que modificam uma chave em um índice também atualizam automaticamente esse índice.
Tópicos
Índices e o espaço de teclas do Redis OSS
Os índices são construídos e mantidos em um subconjunto do espaço de teclas do RedisOSS. Vários índices podem escolher subconjuntos separados ou sobrepostos do espaço de teclas do Redis, sem limitação. 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 OSS espaço de teclas do Redis fará parte desse índice. Os índices também são digitados, pois cobrem apenas as chaves que têm um tipo correspondente. Atualmente, somente HASH índices JSON e índices são suportados. Um HASH índice indexa somente as HASH chaves cobertas por sua lista de prefixos e, da mesma forma, um JSON índice indexa somente as JSON chaves 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.
Quando um JSON comando HASH ou modifica uma chave que está dentro de um espaço de teclas de um índice, esse índice é atualizado. Esse processo envolve a extração dos campos declarados para cada índice e a atualização do índice com o novo valor. O processo de atualização é feito em um thread em segundo plano, o que significa que os índices são consistentes apenas eventualmente com o conteúdo do espaço de chaves. Assim, a inserção ou atualização de uma chave não ficará visível nos resultados da pesquisa por um curto período. Durante períodos de grande carga do sistema e/ou forte mutação de dados, o atraso na visibilidade pode se tornar maior.
A criação de um índice é um processo em várias etapas. O primeiro passo é executar o FT. CREATEcomando 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 examina o espaço de OSS chaves do Redis 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. A conclusão do processo de preenchimento pode ser determinada pela saída do comando FT.INFO
desse índice ('backfill_status').
Tipos de campos de índice
Cada campo (coluna) de um índice tem um tipo específico que é declarado quando esse índice é criado e um local dentro de uma chave. Para HASH chaves, a localização é o nome do campo dentro doHASH. Para JSON chaves, a localização é uma descrição do JSON caminho. 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á quatro tipos de campos, conforme explicado a seguir:
Campos numéricos contêm um único número. Para JSON campos, as regras numéricas dos JSON números devem ser seguidas. PoisHASH, espera-se que o campo contenha o ASCII texto de um número escrito no formato padrão para números fixos ou de ponto flutuante. Independentemente da representação na chave, esse campo é convertido em um número de pontos flutuantes de 64 bits para armazenamento no índice. Campos numéricos podem ser usados com o operador de pesquisa de intervalo. 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.
Os campos de tag contêm zero ou mais valores de tag codificados como uma única string UTF -8. 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. 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.
Os campos de texto contêm um blob de bytes que não precisa ser compatível com UTF -8. Esses campos podem ser usados para decorar resultados de consultas com valores significativos para a aplicação. Por exemplo, a URL ou o conteúdo de um documento, etc.
Campos vetoriais contêm um vetor de números, também conhecido como incorporação. Os campos vetoriais oferecem suporte à pesquisa de K-vizinhos mais próximos (KNN) de vetores de tamanho fixo usando um algoritmo e uma métrica de distância especificados. Para HASH índices, o campo deve conter todo o vetor codificado em formato binário (IEEElittle-endian 754). Para JSON chaves, o caminho deve fazer referência a uma matriz do tamanho correto preenchida com números. Observe que quando uma JSON matriz é usada como um campo vetorial, a representação interna da matriz dentro da JSON chave é convertida no formato exigido pelo algoritmo selecionado, reduzindo o consumo e a precisão da memória. As operações de leitura subsequentes usando os JSON comandos produzirão o valor de precisão reduzido.
Algoritmos de índice vetorial
São fornecidos dois algoritmos de índice vetorial:
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.
HNSW(Hierarchical Navigable Small Worlds) — O HNSW algoritmo é uma alternativa que fornece uma aproximação da resposta correta em troca de tempos de execução substancialmente menores. O algoritmo é controlado por três parâmetros:
M
,EF_CONSTRUCTION
eEF_RUNTIME
. Os dois primeiros parâmetros são especificados no momento da criação do índice e não podem ser alterados. O parâmetroEF_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 a memória e o CPU consumo durante as operações de ingestão e consulta, bem como controlar a qualidade da aproximação de uma KNN pesquisa exata (conhecida como taxa de recuperação).
Ambos os algoritmos de pesquisa vetorial (Flat eHNSW) oferecem suporte a um INITIAL_CAP
parâmetro opcional. 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.
Algoritmos de pesquisa vetorial, por exemplo, HNSW podem não lidar com eficiência com a exclusão ou substituição de vetores inseridos anteriormente. O uso dessas operações pode resultar no consumo excessivo de memória de índice e/ou degradação na qualidade do recall. A reindexação é um dos métodos para restaurar o uso e/ou a recuperação ideais da memória.
Expressão de consulta de pesquisa vetorial
O FT. SEARCHe FT. AGGREGATEos comandos exigem uma expressão de consulta. Essa expressão é um único parâmetro de cadeia de caracteres que é composto por um ou mais operadores. Cada operador usa um campo no índice para identificar um subconjunto das chaves no índice. Vários operadores podem ser combinados usando combinadores boolianos e parênteses para aprimorar ou restringir ainda mais o conjunto coletado de chaves (ou o conjunto de resultados).
Curinga
O operador curinga, o asterisco ('*'), corresponde a todas as chaves no índice.
Intervalo numérico
O operador de intervalo numérico tem a sintaxe a seguir.
<range-search> ::= '@' <numeric-field-name> ':' '[' <bound> <bound> ']' <bound> ::= <number> | '(' <number> <number> ::= <integer> | <fixed-point> | <floating-point> | 'Inf' | '-Inf' | '+Inf'
O < numeric-field-name > deve ser um campo do tipo declaradoNUMERIC
. O limite é inclusivo por padrão, mas um parêntese de abertura inicial ['('] pode ser usado para tornar um limite exclusivo. A pesquisa de intervalo pode ser convertida em uma única comparação relacional (<, <=, >, >=) usando Inf
, +Inf
ou -Inf
como um dos limites. Independentemente do formato numérico especificado (inteiro, ponto fixo, ponto flutuante, infinito), o número é convertido em ponto flutuante de 64 bits para realizar comparações, reduzindo a precisão de acordo.
exemplo Exemplos
@numeric-field:[0 10] // 0 <= <value> <= 10 @numeric-field:[(0 10] // 0 < <value> <= 10 @numeric-field:[0 (10] // 0 <= <value> < 10 @numeric-field:[(0 (10] // 0 < <value> < 10 @numeric-field:[1.5 (Inf] // 1.5 <= value
Comparação de etiquetas
O operador de comparação de etiquetas tem a seguinte sintaxe.
<tag-search> ::= '@' <tag-field-name> ':' '{' <tag> [ '|' <tag> ]* '}'
Se alguma das etiquetas no operador corresponder a qualquer uma das etiquetas no campo de etiqueta do registro, este último será incluído no conjunto de resultados. O campo criado por <tag-field-name>
deve ser um campo do índice declarado com o tipo TAG
. Exemplos de comparação de etiquetas são:
@tag-field:{ atag } @tag-field: { tag1 | tag2 }
Combinações boolianas
Os conjuntos de resultados de um operador numérico ou de etiqueta podem ser combinados usando a lógica booliana: e/ou. Parênteses podem ser usados para agrupar operadores e/ou alterar a ordem de avaliação. A sintaxe dos operadores lógicos boolianos é:
<expression> ::= <phrase> | <phrase> '|' <expression> | '(' <expression> ')' <phrase> ::= <term> | <term> <phrase> <term> ::= <range-search> | <tag-search> | '*'
Vários termos combinados em uma frase são indicados com “e”. Várias frases combinadas com a barra vertical ('|') são indicadas com “ou”.
Pesquisa vetorial
Os índices vetoriais oferecem suporte a dois métodos de pesquisa diferentes: vizinho mais próximo e alcance. Uma pesquisa do vizinho mais próximo localiza um número, K, dos vetores no índice que estão mais próximos do vetor fornecido (de referência) — isso é coloquialmente chamado KNN de “K” dos vizinhos mais próximos. A sintaxe de uma KNN pesquisa é:
<vector-knn-search> ::= <expression> '=>[KNN' <k> '@' <vector-field-name> '$' <parameter-name> <modifiers> ']' <modifiers> ::= [ 'EF_RUNTIME' <integer> ] [ 'AS' <distance-field-name>]
Uma KNN pesquisa vetorial é aplicada somente aos vetores que satisfazem o <expression>
que pode ser qualquer combinação dos operadores definidos acima: curinga, pesquisa por intervalo, pesquisa por tag e/ou combinações booleanas dos mesmos.
<k>
é um número inteiro que especifica o número de vetores vizinhos mais próximos a serem retornados.<vector-field-name>
deve especificar um campo de tipo declaradoVECTOR
.O campo
<parameter-name>
especifica uma das entradas para a tabelaPARAM
do comandoFT.SEARCH
ouFT.AGGREGATE
. Esse parâmetro é o valor vetorial de referência para cálculos de distância. O valor do vetor é codificado noPARAM
valor no formato binário little-endian IEEE 754 (a mesma codificação de um campo vetorial) HASHPara índices vetoriais do tipoHNSW, a
EF_RUNTIME
cláusula opcional pode ser usada para substituir o valor padrão doEF_RUNTIME
parâmetro que foi estabelecido quando o índice foi criado.O
<distance-field-name>
opcional fornece um nome de campo para o conjunto de resultados a fim de conter a distância calculada entre o vetor de referência e a chave localizada.
Uma pesquisa de intervalo localiza todos os vetores dentro de uma distância especificada (raio) de um vetor de referência. A sintaxe para uma pesquisa de intervalo é:
<vector-range-search> ::= ‘@’ <vector-field-name> ‘:’ ‘[’ ‘VECTOR_RANGE’ ( <radius> | ‘$’ <radius-parameter> ) $<reference-vector-parameter> ‘]’ [ ‘=’ ‘>’ ‘{’ <modifiers> ‘}’ ] <modifiers> ::= <modifier> | <modifiers>, <modifier> <modifer> ::= [ ‘$yield_distance_as’ ‘:’ <distance-field-name> ] [ ‘$epsilon’ ‘:’ <epsilon-value> ]
Em que:
<vector-field-name>
é o nome do campo vetorial a ser pesquisado.<radius> or $<radius-parameter>
é o limite numérico de distância para pesquisa.$<reference-vector-parameter>
é o nome do parâmetro que contém o vetor de referência. O valor do vetor é codificado no PARAM valor no formato binário little-endian IEEE 754 (mesma codificação de um campo vetorial) HASHO opcional
<distance-field-name>
fornece um nome de campo para o conjunto de resultados para conter a distância calculada entre o vetor de referência e cada chave.O opcional
<epsilon-value>
controla o limite da operação de pesquisa, vetores dentro da distância<radius> * (1.0 + <epsilon-value>)
são percorridos em busca de resultados candidatos. O padrão é 0,1.
INFOcomando
A pesquisa vetorial aumenta o OSS INFOSEARCH
recuperará todas as seções a seguir:
Seção search_memory
Nome | Descrição |
---|---|
search_used_memory_bytes | Número de bytes de memória consumidos em todas as estruturas de dados de pesquisa |
search_used_memory_human | Versão legível por humanos do valor acima |
Seção search_index_stats
Nome | Descrição |
---|---|
search_number_of_indexes | Número de índices criados |
search_num_fulltext_indexes | Número de campos não vetoriais em todos os índices |
search_num_vector_indexes | Número de campos vetoriais em todos os índices |
search_num_hash_indexes | Número de índices nas chaves de HASH tipo |
search_num_json_indexes | Número de índices nas chaves de JSON tipo |
search_total_indexed_keys | Número total de chaves em todos os índices |
vetores_indexados totais de pesquisa | Número total de vetores em todos os índices |
search_total_indexed_hash_keys | Número total de chaves do tipo HASH em todos os índices |
search_total_indexed_json_keys | Número total de chaves do tipo JSON em todos os índices |
search_total_index_size | Bytes usados por todos os índices |
search_total_fulltext_index_size | Bytes usados por estruturas de índices não vetoriais |
search_total_vector_index_size | Bytes usados por estruturas de índices vetoriais |
search_max_index_lag_ms | Atraso na ingestão durante a última atualização do lote de ingestão |
Seção search_ingestion
Nome | Descrição |
---|---|
search_background_indexing_status | Status da ingestão. NO_ACTIVITY significa ocioso. Outros valores indicam que há chaves em processo de ingestão. |
search_ingestion_paused | Exceto durante a reinicialização, sempre deve ser “no”. |
Seção search_backfill
nota
Alguns dos campos documentados nesta seção apenas são visíveis quando um preenchimento está em andamento.
Nome | Descrição |
---|---|
search_num_active_backfills | Número de atividades atuais de preenchimento |
search_backfills_paused | Exceto quando estiver sem memória, sempre deve ser “no”. |
search_current_backfill_progress_percentage | % de conclusão (0-100) do preenchimento atual |
Seção search_query
Nome | Descrição |
---|---|
search_num_active_queries | Número de comandos FT.SEARCH e FT.AGGREGATE em andamento |
Segurança da pesquisa vetorial
Os mecanismos de segurança do Redis OSS ACL (Access Control Lists)@search
, é fornecida 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 principais, o que significa que o ACL mecanismo existente para acesso de gravação é preservado. As regras de acesso HASH e as JSON operações 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.
Os comandos de pesquisa com um índice também têm seu acesso controlado pelo Redis OSSACL. 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. Pode ser fácil criar uma situação em que um usuário tem acesso de leitura e/ou gravação a uma chave, mas não consegue acessar um índice contendo essa chave. 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.
Para obter mais informações sobre como usar ACLs com o MemoryDB, consulte Autenticação de usuários com listas de controle de acesso (). ACLs