Dicas para melhorar o desempenho do Azure AI Search

Esse artigo é uma coleção de dicas e práticas recomendadas para aumentar o desempenho de consulta e indexação. Saber quais fatores têm mais probabilidade de afetar o desempenho da pesquisa pode ajudar a evitar ineficiências e obter o máximo do serviço de pesquisa. Os principais fatores incluem:

  • Composição de índice (esquema e tamanho)
  • Design de consulta
  • Capacidade do serviço (camada e o número de réplicas e partições)

Observação

Procurando estratégias de indexação de alto volume? Confira Indexar grandes conjuntos de dados no Azure AI Search.

Tamanho e esquema do índice

As consultas são executadas mais rapidamente com índices menores. Isso é, em parte, em função de ter menos campos a ser verificados, mas também devido a como o sistema armazena em cache o conteúdo para consultas futuras. Após a primeira consulta, parte do conteúdo permanece na memória, onde é pesquisada com mais eficiência. Como o tamanho do índice tende a crescer ao longo do tempo, uma prática recomendada é revisitar periodicamente a composição do índice, do esquema e dos documentos, para procurar oportunidades de redução de conteúdo. No entanto, se o índice tiver o tamanho correto, a única outra calibragem possível de se fazer é aumentar a capacidade: seja Adicionar réplicas ou atualizar a camada de serviço. A seção "Dica: Atualizar para um nível Standard S2" fala sobre a decisão de escalar verticalmente versus escalar horizontalmente.

A complexidade do esquema também pode afetar de modo negativo a indexação e o desempenho da consulta. A excessiva atribuição de campos se baseia em limitações e requisitos de processamento. Os Tipos complexos levam mais tempo para indexar e consultar. As próximas seções exploram cada condição.

Dica: Ser seletivo na atribuição de campo

Um erro comum que os administradores e os desenvolvedores cometem ao criar um índice de pesquisa é selecionar todas as propriedades disponíveis para os campos, em vez de selecionar somente as propriedades necessárias. Por exemplo, se um campo não precisar ser pesquisável com texto completo, pule esse campo ao definir o atributo pesquisável.

Atribuição seletiva

O suporte para filtros, facetas e classificações pode quadruplicar os requisitos de armazenamento. Se você adicionar sugestores, os requisitos de armazenamento aumentarão ainda mais. Para obter uma ilustração sobre o impacto dos atributos no armazenamento, consulte Atributos e tamanho do índice.

Resumindo, as ramificações do excesso de atribuição incluem:

  • Degradação do desempenho de indexação devido ao trabalho extra necessário para processar o conteúdo no campo e, em seguida, armazená-lo no índice invertido de pesquisa (definir o atributo "pesquisável" somente em campos que contenham conteúdo pesquisável).

  • Cria uma superfície maior que cada consulta deve cobrir. Todos os campos marcados como pesquisáveis são verificados em uma pesquisa de texto completo.

  • Aumentam os custos operacionais devido ao armazenamento extra. Filtrar e classificar requer espaço adicional para armazenar cadeias de caracteres originais (não analisadas). Evite configurar campos como filtráveis ou classificáveis quando não for necessário.

  • Em muitos casos, a atribuição acima limita os recursos do campo. Por exemplo, se um campo for facetável, filtrável e pesquisável, somente poderá armazenar 16 KB de texto, enquanto um campo pesquisável pode conter até 16 MB de texto.

Observação

Deve ser evitada somente a atribuição desnecessária. Filtros e facetas são geralmente essenciais para a experiência de pesquisa e, nos casos em que os filtros são usados, frequentemente é necessária uma classificação para ordenar os resultados (filtros por si mesmos retornam um conjunto não ordenado).

Dica: Considerar alternativas para tipos complexos

Tipos de dados complexos são úteis quando os dados têm uma estrutura aninhada complicada, como os elementos pai-filho encontrados em documentos JSON. A desvantagem dos tipos complexos são os requisitos de armazenamento extra e os recursos adicionais necessários para indexar o conteúdo, em comparação com tipos de dados não complexos.

Em alguns casos, é possível evitar essas compensações mapeando uma estrutura de dados complexa para um tipo de campo mais simples, como uma Coleção. Como alternativa, é possível optar por nivelar uma hierarquia de campo em campos de nível raiz individuais.

estrutura de campo nivelada

Design de consulta

A composição e a complexidade da consulta são um dos fatores mais importantes para o desempenho, e otimizar a consulta pode melhorar drasticamente o desempenho. Ao criar consultas, pense nos seguintes pontos:

  • Número de campos pesquisáveis. Cada campo pesquisável adicional resulta em mais trabalho para o serviço de pesquisa. É possível limitar os campos que serão pesquisados no momento da consulta usando o parâmetro "searchFields". É melhor especificar apenas os campos nos quais há preocupação em melhorar o desempenho.

  • Quantidade de dados retornados. Recuperar uma grande quantidade de conteúdo pode tornar as consultas mais lentas. Ao estruturar uma consulta, retorne apenas os campos necessários para renderizar a página resultados e, em seguida, recupere os campos restantes usando a API de pesquisa quando um usuário selecionar uma correspondência.

  • Uso de pesquisas de termo parcial. Pesquisas de termo parcial, como pesquisa de prefixo, pesquisa difusa e pesquisa de expressão regular, são mais caras em termos de computação de palavras-chave comuns, pois exigem verificações de índice completas para produzir resultados.

  • Número de facetas. Adicionar facetas a consultas requer agregações para cada consulta. Solicitar uma "contagem" maior para uma faceta também requer trabalho extra pelo serviço. Em geral, adicione apenas as facetas que você planeja renderizar no aplicativo e evite solicitar uma contagem alta para facetas, a menos que necessário.

  • Valores skip alto. Definir o parâmetro $skip como um valor alto (por exemplo, em milhares) aumenta a latência de pesquisa porque o mecanismo está recuperando e classificando um volume maior de documentos para cada solicitação. Por motivos de desempenho, é melhor evitar valores $skip altos e usar outras técnicas, como filtragem, para recuperar um grande número de documentos.

  • Limitar campos de alta cardinalidade. Um campo de alta cardinalidade refere-se a um campo facetável ou filtrável que tem um número considerável de valores exclusivos e, como resultado, consome recursos significativos no cálculo dos resultados. Por exemplo, a configuração de um campo de ID ou Descrição do Produto como facetável e filtrável será contado como de alta cardinalidade, pois a maioria dos valores de cada documento é única.

Dica: Usar as funções de pesquisa em vez de sobrecarregar os critérios de filtro

Como uma consulta usa, cada vez mais critérios de filtro complexos, o desempenho da consulta de pesquisa ficará prejudicado. Considere o exemplo a seguir que demonstra o uso de filtros para cortar resultados com base em uma identidade de usuário:

$filter= userid eq 123 or userid eq 234 or userid eq 345 or userid eq 456 or userid eq 567

Nesse caso, as expressões de filtro são usadas para verificar se um único campo em cada documento é igual a um dos muitos valores possíveis de uma identidade de usuário. É mais provável encontrar esse padrão em aplicativos que implementam a filtragem de segurança (verificar um campo que contém uma ou mais IDs de entidade de segurança em relação a uma lista de IDs de entidades de segurança que representam o usuário que está emitindo a consulta).

Uma maneira mais eficiente de executar filtros que contêm um grande número de valores é usar a search.in função, conforme mostrado neste exemplo:

search.in(userid, '123,234,345,456,567', ',')

Dica: Adicionar partições para consultas individuais lentas

Quando o desempenho da consulta está diminuindo no geral, adicionar mais réplicas geralmente resolve o problema. Mas, e se o problema for uma única consulta que leva muito tempo para ser concluída? Nesse cenário, a adição de réplicas não ajudará, mas talvez partições adicionais ajudem. Uma partição divide os dados em recursos de computação extra. Duas partições dividem os dados pela metade, uma terceira partição divide-os em terços e assim por diante.

Um efeito colateral positivo da adição de partições é que as consultas mais lentas às vezes são executadas mais rapidamente devido à computação paralela. Observamos a paralelização em consultas de baixa seletividade, como consultas que correspondem a muitos documentos ou facetas que fornecem contagens de um grande número de documentos. Como uma computação significativa é necessária para pontuar a relevância dos documentos ou para contar os números de documentos, adicionar partições extras ajuda as consultas a serem concluídas com mais rapidez.

Para adicionar partições, use portal do Azure, PowerShell, CLI do Azureou um SDK de gerenciamento.

Capacidade do serviço

Um serviço é sobrecarregado quando as consultas levam muito tempo ou quando o serviço começa a cancelar as solicitações. Se isso acontecer, é possível resolver o problema atualizando o serviço ou adicionando capacidade.

A camada do serviço de pesquisa e o número de réplicas/partições também têm um grande impacto sobre o desempenho. Cada camada progressivamente mais alta fornece CPUs mais rápidas e mais memória, que têm um impacto positivo no desempenho.

Dica: crie um serviço de pesquisa de alta capacidade

Os serviços básicos e padrão criados nas regiões com suporte após 3 de abril de 2024 têm mais armazenamento por partição do que os serviços mais antigos. Antes de fazer upgrade para uma camada superior e para uma taxa faturável mais alta, revise os limites do serviço de camadas para entender se a mesma camada em um serviço mais recente oferece o armazenamento necessário.

Dica: Atualizar para uma camada Standard S2

A camada de pesquisa Standard S1 geralmente é onde os clientes iniciam. Um padrão comum para serviços S1 é que os índices crescem ao longo do tempo, o que exige mais partições. Mais partições levam a tempos de resposta mais lentos, portanto, mais réplicas são adicionadas para lidar com a carga de consulta. Como você pode imaginar, o custo da execução de um serviço S1 agora progrediu para níveis além da configuração inicial.

Nesse momento, uma pergunta importante a ser feita é se seria benéfico mudar para uma camada mais alta, em vez de aumentar progressivamente o número de partições ou réplicas do serviço atual.

Considere a seguinte topologia como um exemplo de um serviço que obteve níveis crescentes de capacidade:

  • Camada Standard S1
  • Tamanho do índice: 190 GB
  • Contagem de partições: 8 (em S1, o tamanho da partição é 25 GB por partição)
  • Contagem de Réplicas: 2
  • Total de Unidades de pesquisa: 16 (8 partições x 2 réplicas)
  • Preço hipotético de varejo: ~US$ 4.000 /mês (suponha 250 USD x 16 unidades de pesquisa)

Suponha que o administrador de serviços ainda observe taxas de latência mais altas e esteja considerando adicionar outra réplica. Isso alteraria a contagem de réplicas de 2 para 3 e, como resultado, alteraria a contagem de unidades de pesquisa para 24 e um preço resultante de $6.000 USD/mês.

No entanto, se o administrador optasse por mudar para uma camada Standard S2, a topologia teria esta aparência:

  • Camada Standard S2
  • Tamanho do índice: 190 GB
  • Contagem de partições: 2 (na S2, o tamanho da partição é 100 GB por partição)
  • Contagem de Réplicas: 2
  • Total de Unidades de pesquisa: 4 (2 partições x 2 réplicas)
  • Preço hipotético de varejo: ~US$ 4.000 USD/mês (1.000 USD x 4 unidades de pesquisa)

Como este cenário hipotético ilustra, é possível ter configurações em camadas inferiores que resultam em custos semelhantes, como se tivesse optado por uma camada mais alta desde o início. No entanto, as camadas mais altas são fornecidas com o armazenamento Premium, o que torna a indexação mais rápida. As camadas mais altas também têm muito mais poder de computação, bem como memória extra. Para os mesmos custos, é possível ter uma infraestrutura mais potente de suporte para o mesmo índice.

Um benefício importante da memória adicionada é que pode ser armazenado em cache uma parte maior do índice, resultando em latência de pesquisa mais baixa e um número maior de consultas por segundo. Com esse poder extra, talvez o administrador não precise nem mesmo aumentar a contagem de réplicas e possa pagar menos do que permanecendo no serviço S1.

Dica: considere alternativas para consultas de expressão regular

As consultas de expressão regular ou regex podem ser particularmente caras. Embora possam ser muito úteis para pesquisas avançadas, a execução pode exigir muito poder de processamento, especialmente se a expressão regular for complicada ou se você estiver pesquisando uma grande quantidade de dados. Todos esses fatores contribuem para a alta latência de pesquisa. Como mitigação, tente simplificar a expressão regular ou dividir a consulta complexa em consultas menores e mais gerenciáveis.

Próximas etapas

Examine estes outros artigos relacionados ao desempenho do serviço: