Pesquisa de texto completo

Aprimoramentos de desempenho do FTS na versão 6.5.0 - Parte 2

Para todos aqueles que estão ansiosos, vou revelar o segredo obscuro de todas as otimizações de desempenho do FTS na versão 6.5.0,

" Faça menos e com menos frequência ** "

E tenho certeza de que você concordará comigo ao rolar a página mais abaixo.

(Para aqueles que perderam - Parte 1)

 

Coletar dispersão sobre gRPC

 

Normalmente, um índice FTS é particionado em subíndices e as partições de índice são colocadas em nós em um cluster de vários nós. Qualquer consulta de pesquisa de entrada típica é então espalhada por todos esses nós/partições de índice remoto e os resultados da pesquisa são reunidos de diferentes nós, mesclados por classificação e enviados de volta ao usuário pelo nó de coordenação ou de tratamento da consulta.  

Até o lançamento da versão 6.5.0, toda a coleta de dispersão no FTS ocorre por http/http2. Afastar-se dessa coleta de dispersão baseada em REST era um item pendente há muito tempo no backlog da equipe. A procrastinação foi benéfica para nós aqui.

Com o surgimento dos recursos da versão 6.5.0, como a integração N1QL-FTS, percebemos que era o momento certo para experimentar o gRPC para a coleta de dispersão interna. Como já se falou muito sobre os prós do gRPC em toda a Web, vou me abster de repetir aqui.

Com o FTS, estávamos interessados principalmente em explorar os recursos de streaming e multiplexação de solicitações do gRPC. A transmissão de volta dos resultados da pesquisa para os clientes ajuda a abordar o caso de uso de servir um resultado de pesquisa com milhões de resultados não classificados (com classificação constante) de uma forma mais amigável à memória.

 

Os desafios interessantes foram,

 

  • Obter as interfaces corretas para permitir que o pacote cbft de nível mais alto grave os resultados da pesquisa no fluxo do cliente de maneira configurável (por exemplo, lote de ocorrências ou uma única ocorrência) à medida que os iteradores da biblioteca de indexação percorrem os documentos correspondentes em algum lugar dentro do mecanismo de armazenamento.

 

  • Definição dos tipos corretos de mensagens protobuf no contexto dos tipos de mensagens existentes.

 

Obter a mensagem protobuf correta não foi muito simples, pois o FTS já tinha os tipos de mensagem json estabelecidos, que estavam intimamente ligados aos tipos internos da Golang, e todos os nossos clientes os utilizam. Portanto, qualquer formato de mensagem mais recente tinha que levar em consideração os tipos de mensagem herdados. Isso introduz um nível extra de esforços de marshal/unmarshal entre esses tipos Go e os novos tipos protobuf. E isso, de fato, acionou o botão de pânico durante os testes iniciais, devido aos significativos danos em nossos gráficos de desempenho. 

 

Resolvemos imediatamente esse problema cortando as despesas gerais de análise da mensagem de pesquisa herdada do novo tipo de mensagem protobuf. A ideia era incorporar toda a mensagem de pesquisa legada como uma fatia de byte dentro da nova mensagem proto, o que eliminou alguns desvios e gerou muito menos lixo.

 

Resultado

A coleta de dispersão baseada em gRPC mostrou um 2X melhoria da taxa de transferência para consultas de termos de baixa frequência em nossos benchmarks internos com um cluster de 3 nós.

 

 

Consulta de intervalo numérico 

A biblioteca de indexação de texto que usamos (sangrar) armazena os valores do campo numérico em diferentes pontos de precisão, ou seja, um único valor de campo numérico é indexado como vários tokens codificados em binário deslocado. Embora essa abordagem aumente o tamanho do índice, no momento da consulta isso resultará em menos termos a serem pesquisados para um determinado intervalo numérico e, portanto, torna essas consultas muito mais rápidas.

 

Oportunidade

Semelhante ao modus operandi das consultas geográficas mencionadas em Parte 1 desta série, a implementação da consulta de intervalo numérico também deriva os termos numéricos exatos (termos candidatos) a serem pesquisados matematicamente. A lógica de filtragem de termos candidatos à pesquisa usada para a consulta de intervalo numérico é semelhante à das consultas fuzzy/regex. Ela tentará filtrar os termos candidatos por meio da interseção dos dois DFAs, ou seja, a interseção entre o dicionário de termos e o DFA/FST temporário criado a partir dos intervalos numéricos criados matematicamente. No entanto, com base no perfil do gráfico de chama do Golang, essa abordagem se mostrou menos eficiente em termos de memória e CPU.

Aprimoramos essa lógica de filtragem com uma API de pesquisa de dicionário de termos mais limpa e mais leve, o que ajudou a controlar o uso da memória e da CPU. E isso removeu os picos extras que apareciam nos gráficos de chamas.

 

Resultado

Essa mudança trouxe 77% melhorias na taxa de transferência em testes de desempenho interno do FTS que tinham um fluxo constante de mutações recebidas (10 mil conjuntos/segundos). 

 

Consultas de prefixo/fuzzy/cartão selvagem 

Oportunidade

Todos esses tipos de consulta fazem uso intenso de travessias FST. As consultas de prefixo aproveitam os iteradores FST baseados em intervalo, enquanto as curingas/fuzzy usam os iteradores baseados em autômatos, ou seja, um autômato regex para consultas curingas/regex e um autômato levenshtein para as consultas fuzzy.

Identificamos as estruturas compartilháveis simultaneamente entre essas consultas e as armazenamos em cache em um segmento para melhorar a reutilização entre as consultas. Esse método reduziu bastante a quantidade de lixo criado e nos ajudou a economizar nos ciclos de GC.

 

Resultado

O melhor armazenamento em cache e a reutilização ajudaram a melhorar os números de taxa de transferência para -
Wildcard por 25%,  Fuzzy por 12%, Prefixo por 9%.

 

 

{** Há apenas três otimizações: "Faça menos. Faça com menos frequência. Faça mais rápido".
Os maiores ganhos vêm de 1, mas gastamos todo o nosso tempo em 3.- Michael Fromberger}

Compartilhe este artigo
Receba atualizações do blog do Couchbase em sua caixa de entrada
Esse campo é obrigatório.

Autor

Postado por Sreekanth Sivasankaran

Sreekanth Sivasankaran é engenheiro principal/gerente sênior de engenharia da Couchbase R&D. Ele lidera o projeto e o desenvolvimento da funcionalidade de pesquisa distribuída e de alto desempenho. Ele tem mais de 17 anos de experiência em desenvolvimento de produtos em vários domínios, como telecomunicações, telefones celulares, software corporativo, tecnologias de big data e sistemas distribuídos.

Deixe um comentário

Pronto para começar a usar o Couchbase Capella?

Iniciar a construção

Confira nosso portal do desenvolvedor para explorar o NoSQL, procurar recursos e começar a usar os tutoriais.

Use o Capella gratuitamente

Comece a trabalhar com o Couchbase em apenas alguns cliques. O Capella DBaaS é a maneira mais fácil e rápida de começar.

Entre em contato

Deseja saber mais sobre as ofertas do Couchbase? Deixe-nos ajudar.