Otimizar indexação, custo da pesquisa vetorial e consistência no Azure Cosmos DB
Converta padrões reais de consulta em índices seletivos de intervalo, compostos, de tupla e vetoriais, meça a eficiência em RU e escolha garantias de consistência sem custo desnecessário.
Tempo de estudo sugerido: 115 minutos • Nível intermediário • Reescrita autoral completa com versão resumida de cada tópico, avaliação comentada e laboratório guiado de desempenho
Por João Ricardo Dutra••Conteúdo autoral completo
1. Diagnosticar a pesquisa em produção antes de adicionar índices
Uma plataforma de pesquisa semântica pode funcionar bem com poucos dados e falhar quando chega à produção. Imagine milhões de itens com , texto extraído e embeddings gerados pelo . Os usuários combinam palavras-chave, intervalos de data, tipos de documento e classificação semântica, esperando respostas abaixo de 100 milissegundos. Em escala real, a latência sobe, as cobranças de RU disparam e uploads recentes nem sempre aparecem na busca imediata.
As causas se complementam: a política padrão cria índice de intervalo para todas as propriedades, inclusive grandes matrizes de embeddings; índices compostos necessários não existem e algumas consultas fazem varredura; e a consistência eventual não garante que o próprio autor leia imediatamente sua gravação. A correção começa pelo catálogo dos padrões de consulta, pelas métricas e pela necessidade de atualização percebida pelo usuário.
Localizar filtros, ordenações e consultas vetoriais de baixo desempenho.
Configurar índices de intervalo e compostos conforme o acesso real.
Escolher flat, quantizedFlat ou DiskANN conforme volume e qualidade.
Equilibrar ganhos de leitura com custo de gravação, armazenamento e transformação.
Selecionar consistência suficiente sem pagar por uma garantia desnecessária.
Resumo do tópico
A otimização de produção começa por evidências de consulta e requisitos de atualização, não pela criação indiscriminada de índices.
2. Compreender indexação automática, famílias de índice e modos
Um novo contêiner do for indexa automaticamente todas as propriedades com índices de intervalo. Isso acelera a prototipagem, pois quase qualquer filtro escalar já encontra suporte, mas cada caminho indexado ocupa espaço e aumenta o trabalho síncrono de cada gravação. Cargas de IA com acesso previsível geralmente ganham com uma política seletiva.
Famílias de índice e os padrões atendidos.
Família
Uso principal
Intervalo
Igualdade, comparação, ORDER BY em uma propriedade, funções de cadeia de caracteres e IS_DEFINED.
Composto
ORDER BY em várias propriedades e combinações frequentes de igualdade e intervalo.
Espacial
ST_DISTANCE, ST_WITHIN e ST_INTERSECTS para dados geográficos.
Vetorial
Similaridade de embeddings com VectorDistance.
Tupla
Vários campos pertencentes ao mesmo elemento de uma matriz.
Texto completo
Pesquisa textual tratada em outro capítulo da trilha AI-200.
O modo consistente atualiza o índice durante a gravação e é a escolha normal quando dados recém-ingeridos precisam ser consultáveis. O modo none desabilita índices secundários e serve a leituras pontuais por id e chave de partição ou a situações específicas de carga em massa. A indexação lenta (lazy) foi descontinuada para novos contêineres; usos antigos devem migrar para o modo consistente.
Resumo do tópico
A política automática amplia a cobertura; uma política consistente personalizada reduz armazenamento e trabalho de gravação sem utilidade.
3. Controlar caminhos incluídos, excluídos e propriedades do sistema
As expressões de caminho definem o que entra no índice. /* inclui recursivamente propriedades escalares desde a raiz, /property/? seleciona um valor escalar, /array/[] cobre os elementos de uma matriz e /nested/path/* cobre os descendentes. Em caso de conflito, prevalece a regra mais específica, permitindo excluir uma árvore ampla e reincluir somente os pontos necessários.
id e _ts permanecem indexados no modo consistente e não podem ser desabilitados.
_etag é excluído por padrão e raramente precisa ser incluído.
Quando não é /id, a chave de partição não recebe índice de intervalo automaticamente; inclua-a se aparecer em filtros.
Exclua textos extensos apenas exibidos, dados binários, brutos e embeddings que não participam de filtros ou ordenações.
Uma única política coordena acesso escalar, composto e vetorial sem indexar que nunca aparecem em consultas.
Resumo do tópico
Na estratégia de exclusão por padrão, inclua explicitamente a chave de partição e todas as propriedades realmente consultadas.
4. Projetar índices de intervalo para filtros e funções de texto
Índices de intervalo aceitam =, !=, >, <, >= e <=, além de ordenação por uma propriedade. Também atendem CONTAINS, STARTSWITH, ENDSWITH, StringEquals e IS_DEFINED quando a propriedade indexada ocupa a posição esperada. Uma consulta por documentType e uploadDate precisa dos dois caminhos; sem eles, a RU cresce com o volume examinado, e não com os resultados entregues.
Eles são a base para tipo, status, categoria, datas, pontuações e limites numéricos. Não substituem o índice de texto completo em pesquisa linguística e não devem ser aplicados a embeddings só porque a matriz contém números.
Resumo do tópico
Use índices de intervalo para valores escalares, comparações e ordenação simples; deixe embeddings para o índice vetorial dedicado.
5. Fazer o índice composto corresponder a ORDER BY e múltiplos filtros
Uma ordenação por duas ou mais propriedades exige um índice composto com a mesma sequência e direção. Um índice relevanceScore DESC e uploadDate DESC também atende a inversão completa para ASC, mas não a uma combinação de direções. Alterar a ordem dos caminhos cria outro padrão.
Para filtrar por documentType e ordenar por uploadDate, repetir a propriedade de igualdade no ORDER BY permite que o índice composto resolva o prefixo fixo e o sufixo ordenado.
SELECT * FROM c
WHERE c.documentType = 'pdf'
ORDER BY c.documentType ASC, c.uploadDate DESC
Em filtros com várias propriedades, coloque as igualdades primeiro e no máximo uma condição de intervalo por último. Com dois intervalos, o mecanismo pode combinar dois índices compostos, ambos iniciados pelos campos de igualdade e cada um encerrado por um dos intervalos. Priorize combinações frequentes e de alto volume em vez de criar dezenas de índices para exceções.
Resumo do tópico
Índices compostos dependem da ordem: igualdades formam o prefixo, um intervalo encerra a definição e a ordenação precisa corresponder ao índice.
6. Usar índices de tupla e alterar políticas com segurança
O índice de tupla mantém relacionados os campos do mesmo elemento de uma matriz. Ele é adequado para com posição e quantidade de , tags com categoria e peso ou eventos com horário e tipo. Sem essa semântica, o mecanismo não representa com eficiência que todos os predicados devem ocorrer no mesmo membro da matriz.
Todo índice eleva a latência e a RU de gravação porque o modo consistente o mantém sincronamente. Mudanças de política geram uma transformação assíncrona. Um índice adicionado só ajuda depois de 100% da transformação; um índice removido deixa de servir consultas imediatamente. Ao substituir, adicione a nova definição, aguarde e valide a transformação e somente então exclua a antiga. Monitore pelo portal do ou por superfícies compatíveis dos SDKs e planeje grandes alterações fora do pico.
Resumo do tópico
Índices de tupla resolvem filtros no mesmo elemento; a substituição segura segue adicionar, aguardar, validar e remover.
7. Selecionar o índice vetorial para o escopo pesquisado
Índices vetoriais aceleram VectorDistance, enquanto índices de intervalo e compostos atendem aos . A política vetorial do contêiner define caminho, tipo dos elementos, dimensões e função de distância; depois, a política de indexação associa flat, quantizedFlat ou diskANN a esse caminho.
Decisão entre índices vetoriais.
Tipo
Comportamento e limite
Escopo típico
flat
exata; até 505 dimensões.
Poucos candidatos ou necessidade de 100% de recall.
quantizedFlat
Vetores compactados examinados por ; até 4.096 dimensões e possível pequena perda de recall.
Cerca de 1.000 a 50.000 vetores por partição física ou pesquisa muito filtrada.
diskANN
Vizinhos aproximados com algoritmos da Microsoft Research; até 4.096 dimensões.
Mais de aproximadamente 50.000 vetores por partição física, baixa latência e eficiência de RU.
quantizedFlat e diskANN precisam de pelo menos 1.000 vetores para que a estrutura otimizada se torne efetiva; abaixo disso, ocorre uma varredura completa. Uma aplicação crescente pode começar com flat e migrar depois de testes representativos. Sempre exclua embeddings do índice de intervalo.
O número de candidatos depois da partição e dos filtros de importa mais do que o tamanho total da conta.
Resumo do tópico
Escolha o índice pelo número de candidatos, dimensões, recall, latência e RU; não existe um padrão universal.
8. Ajustar a construção vetorial e coordenar filtros de
Comece pelos padrões do serviço. quantizationByteSize aceita 1 a 512 bytes: valores maiores preservam mais informação, com mais armazenamento. No diskANN, indexingSearchListSize aceita 10 a 500 e tem padrão 100; aumentar a lista pode melhorar o recall, mas encarece a construção do índice e a entrada de novos vetores.
Combine o índice vetorial com índices de intervalo ou compostos em categoria, departamento, tipo e data. A pré-filtragem seletiva reduz os candidatos antes ou durante a similaridade e pode cortar bastante a RU. A política vetorial é uma decisão estrutural: mudar dimensões, tipo de dados ou distância normalmente exige outro contêiner compatível e migração. float16 ocupa cerca de metade de float32 com impacto geralmente pequeno; int8 e uint8 exigem quantização medida. Cosseno é comum em embeddings de texto.
Resumo do tópico
Ajuste parâmetros apenas com métricas de recall e latência e defina dimensões, tipo e distância antes da produção.
9. Medir a eficiência e descobrir índices ausentes
Métricas de consulta transformam lentidão em evidência. A utilização do índice mostra quanto do trabalho foi indexado, a quantidade de documentos recuperados mostra o volume lido para avaliação e a quantidade de saída mostra quantos sobreviveram. Baixa utilização ou uma relação recuperados/saída muito alta costuma indicar varredura, caminho ausente ou índice composto faltante.
from azure.cosmos import CosmosClient
metrics = {}
def response_hook(headers, _):
metrics["query"] = headers.get("x-ms-documentdb-query-metrics", "")
metrics["ru"] = headers.get("x-ms-request-charge", "")
items = list(container.query_items(
query="SELECT * FROM c WHERE c.documentType = @type ORDER BY c.uploadDate DESC",
parameters=[{"name": "@type", "value": "pdf"}],
populate_query_metrics=True,
response_hook=response_hook
))
print(metrics["query"])
print(f'{metrics["ru"]} RUs')
Capture x-ms--charge, altere uma hipótese de cada vez, espere a transformação e repita o mesmo teste. TOP pode limitar a saída, mas não corrige um filtro sem índice. Compare percentis e padrões representativos, não uma única execução conveniente.
Resumo do tópico
Utilização, documentos recuperados/retornados e cobrança de RU provam se a mudança realmente reduziu trabalho.
10. Equilibrar custo de RU entre leituras e gravações
Leituras indexadas tendem a consumir RU conforme o conjunto de resultados; varreduras crescem com os dados. Em contrapartida, cada caminho e índice composto ocupa armazenamento e aumenta RU de gravação. Pesquisa, relatórios e painéis com muitas leituras justificam mais cobertura; intensa, atualizações frequentes de embeddings, e lotes favorecem menos índices.
Catalogar WHERE, ORDER BY, agregações, combinações, direções e frequência.
Cobrir os cinco a dez padrões que entregam maior benefício medido.
Retirar do índice de intervalo texto apenas exibido, brutos e vetores.
Testar cardinalidade, assimetria, distribuição entre partições e contagem de vetores realistas.
Comparar RU de leitura e gravação antes de aprovar a política.
Dados sintéticos uniformes escondem categorias quentes e partições desiguais. Carregue distribuições semelhantes às de produção, execute consultas representativas e escolha pelo custo total medido.
Resumo do tópico
A melhor política minimiza o custo total: muitas leituras justificam índices; muitas gravações premiam seletividade.
11. Comparar os cinco níveis de consistência e o efeito em RU
Garantias de consistência e custo de leitura.
Nível
Garantia e uso típico
RU relativa
Forte
Leitura linearizável do último valor confirmado; dados regulados ou críticos. Incompatível com várias regiões de gravação.
2×
Desatualização limitada
Atraso limitado a K versões ou T tempo; limite previsível com uma região de gravação.
2×
Sessão
Read-your-writes dentro da sessão; opção prática para aplicações voltadas ao usuário.
1×
Prefixo consistente
Nunca observa gravações fora de ordem, embora possam estar desatualizadas; e sequências.
1×
Eventual
Sem promessa de atualização ou ordem; maior taxa de transferência e menor latência para análise e processamento em segundo plano.
1×
Forte e desatualização limitada consultam duas réplicas; por isso, a taxa de leitura por RU fica aproximadamente na metade dos níveis de sessão, prefixo consistente e eventual. A RU da operação de gravação é igual entre os níveis, mas a consistência forte espera a maioria global e aumenta a latência. Os níveis mais fracos confirmam a maioria local antes da replicação assíncrona entre regiões.
Escolha a garantia mais fraca que ainda satisfaz a interação de negócio.
Resumo do tópico
Consistência equilibra atualização, latência, disponibilidade e custo; mais forte não significa automaticamente melhor.
12. Garantir read-your-writes com de sessão e observar PBS
A consistência de sessão é adequada quando o usuário precisa encontrar imediatamente o documento ou embedding que acabou de enviar. O representa o avanço dentro de uma partição. Uma instância do o gerencia automaticamente, mas serviços distribuídos precisam propagar o da gravação para a leitura. Outras sessões ainda podem observar dados antigos por um curto período.
Instâncias separadas do cliente podem usar consistência mais forte em leituras críticas e eventual em análises. Em múltiplas regiões, a forte espera as regiões distantes e não aceita várias regiões de gravação; a desatualização limitada combina melhor com uma região de gravação; sessão e níveis mais fracos confirmam localmente. A métrica Desatualização Limitada Probabilística (PBS) no mostra com que frequência uma leitura eventual já devolve dados atuais e ajuda a decidir se a garantia pode ser enfraquecida.
Resumo do tópico
Propague de sessão entre serviços para visibilidade imediata e use PBS antes de enfraquecer a consistência percebida pelo usuário.
13. Laboratório guiado: comparar índices vetoriais com dados realistas
O exercício de referência propõe 30 minutos para comparar flat, quantizedFlat e diskANN. São necessários uma assinatura do com permissão de implantação, , a versão mais recente da CLI do e Python 3.12 ou posterior. Use um grupo de recursos descartável e exclua-o após registrar os resultados.
Obter os arquivos iniciais e parametrizar a implantação.
Implantar uma conta do for com pesquisa vetorial habilitada.
Criar três contêineres idênticos, alterando apenas o tipo do índice vetorial.
Carregar os mesmos documentos e embeddings em todos.
Criar funções Python que executem as mesmas consultas VectorDistance, com e sem filtros.
Exibir latência, cobrança de RU e coincidência dos melhores resultados em uma aplicação Flask.
Repetir com pelo menos 1.000 vetores e seletividade realista de .
Registrar recall em relação ao flat, latência mediana e de cauda, RU e armazenamento e escolher a opção que atende ao alvo.
Não compare índices com dados, partições, vetores de consulta ou filtros diferentes. Aquecimento e coleções pequenas distorcem o resultado; repita cada cenário e relate a distribuição.
Resumo do tópico
Um benchmark justo mantém dados e consultas constantes e compara recall, latência, RU e armazenamento em escala representativa.
14. Revisão comentada da avaliação
Filtro por documentType e ordenação uploadDate DESC: índice composto iniciado por documentType ASC e encerrado por uploadDate DESC.
Cerca de 500.000 embeddings por partição e aproximação aceitável: diskANN é a opção voltada à escala.
Embeddings usados só em similaridade: excluir o caminho do índice de intervalo e manter o índice vetorial.
O usuário precisa enxergar o próprio upload: consistência de sessão e da gravação propagado para a leitura.
Baixa utilização e alta relação recuperados/saída: a consulta está varrendo; examine os predicados e adicione índice de intervalo ou composto.
Os distratores representam erros comuns: índices de intervalo separados não atendem uma ordenação multipropriedade, desligar toda a indexação prejudica consultas alheias, aumentar a taxa de transferência não cria garantia de atualização e TOP não corrige filtragem ineficiente.
Resumo do tópico
A resposta correta segue o formato da consulta, a escala vetorial, o armazenamento, a garantia de atualização e a métrica observada.
15. Checklist final e referências oficiais
Inventariar consultas antes de escrever a política.
Indexar a chave de partição quando a política de exclusão por padrão ainda a filtra.
Usar intervalo, composto, espacial, tupla e vetorial somente nos padrões compatíveis.
Excluir embeddings do índice de intervalo e medir o escopo real da busca vetorial.
Adicionar o índice substituto antes de remover o antigo.
Validar RU e latência com dados realistas e transformação concluída.
Usar consistência de sessão para visibilidade imediata e garantias mais fracas onde atrasos são aceitáveis.
Pesquisa eficiente combina indexação seletiva, escolhas vetoriais medidas, transformações seguras e a consistência menos cara que preserva a experiência exigida.