Todos os produtos
Search
Central de documentação

Tablestore:Como otimizar o desempenho da consulta vetorial KNN do Tablestore?

Última atualização: Jul 03, 2026

O recurso de consulta vetorial k-nearest neighbor (KNN) do Tablestore identifica itens de dados com maior similaridade em relação ao vetor consultado em conjuntos de dados de grande escala. Caso os resultados de uma busca semântica via consulta vetorial KNN não atendam às expectativas, siga as instruções de solução de problemas deste tópico para otimizar o desempenho do recurso.

Fórmulas de pontuação da consulta vetorial KNN

Nota

A consulta vetorial KNN do Tablestore executa buscas aproximadas de vizinhos mais próximos baseadas em vetores. Esse recurso atende a diversos cenários, como geração aumentada por recuperação (RAG), sistemas de recomendação, detecção de similaridade, processamento de linguagem natural (NLP) e busca semântica. Para mais informações, consulte Usar consulta vetorial KNN.

A consulta vetorial KNN suporta os seguintes algoritmos de medição de distância para vetores: euclidean, dot_product e cosine. A fórmula de pontuação usada para calcular a distância entre vetores varia conforme o algoritmo de medição escolhido. O Tablestore utiliza essas fórmulas para medir a similaridade entre vetores. A tabela a seguir descreve as fórmulas de pontuação.

Tipo de métrica

Fórmula de pontuação

euclidean

image

dot_product

image

cosine

image

Solução de problemas e análise

1. Verifique o método de ordenação

Ao usar a consulta vetorial KNN, confirme se o método de ordenação está definido como ScoreSort para classificar os resultados por pontuação. Por padrão, o sistema ordena os resultados pela chave primária.

2. Ajuste a combinação de KnnVectorQuery e BoolQuery

Ao combinar KnnVectorQuery e BoolQuery, defina o tipo de consulta do índice de busca como KnnVectorQuery. Incluir as condições de BoolQuery no filtro da consulta vetorial KNN (Filter) não afeta a pontuação.

Importante

Se você definir o tipo de consulta como BoolQuery e especificar KnnVectorQuery como subconsulta de BoolQuery, outras condições da BoolQuery poderão afetar a pontuação. Para mais informações, consulte Apêndice 1: Uso com BoolQuery.

O exemplo de código Java a seguir demonstra como utilizar o recurso de consulta vetorial KNN:

private static void knnVectorQuery(SyncClient client) {
    SearchQuery searchQuery = new SearchQuery();
    KnnVectorQuery query = new KnnVectorQuery();
    query.setFieldName("Col_Vector");
    query.setTopK(10); // Return the top 10 vectors in the table that have the highest similarity to the specified vector. 
    query.setFloat32QueryVector(new float[]{0.1f, 0.2f, 0.3f, 0.4f});
    // Specify the query conditions for the top 10 vectors: the value of the Col_Keyword column is hangzhou and the value of the Col_Long column is less than 4. 
    query.setFilter(QueryBuilders.bool()
            .must(QueryBuilders.term("Col_Keyword", "hangzhou"))
            .must(QueryBuilders.range("Col_Long").lessThan(4))
    );
    searchQuery.setQuery(query);
    searchQuery.setLimit(10);
    // Sort the query results by score. 
    searchQuery.setSort(new Sort(Collections.singletonList(new ScoreSort())));
    SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);
    SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
    columnsToGet.setColumns(Arrays.asList("Col_Keyword", "Col_Long"));
    searchRequest.setColumnsToGet(columnsToGet);
    // Call the Search operation. 
    SearchResponse resp = client.search(searchRequest);
    for (SearchHit hit : resp.getSearchHits()) {
        // Display the scores. 
        System.out.println(hit.getScore());
        // Display the data. 
        System.out.println(hit.getRow());
    }
}

3. Analise o desempenho da geração de vetores

O Tablestore calcula a similaridade entre vetores, mas não avalia se o desempenho da geração desses vetores é ideal. Tanto os vetores armazenados quanto o vetor de consulta são gerados por modelos de Embedding externos. Em domínios especializados, os vetores gerados podem ser imprecisos. Para solucionar problemas de baixo desempenho na geração de vetores, execute as etapas abaixo:

  1. Utilize métodos ou ferramentas externas ao Tablestore para pontuação.

    1. Nomeie o vetor que deseja consultar como Vector a e o vetor retornado da tabela do Tablestore como Vector b.

      Nota

      Obtenha os dados do Vector b usando um índice de busca, um índice secundário ou a operação de leitura de dados de uma tabela no modelo Wide Column.

    2. Calcule a Score a, que representa a similaridade entre Vector a e Vector b, utilizando o método MetricFunction.COSINE.compare(a, b) descrito em Apêndice: Código de exemplo das fórmulas de pontuação da consulta vetorial KNN.

  2. Use o Tablestore para pontuação.

    Execute uma consulta vetorial KNN no Tablestore para buscar o Vector a e verifique a Score b de cada linha na resposta.

  3. Compare e analise as pontuações.

    Caso nenhuma linha contendo o Vector b seja encontrada na consulta vetorial KNN do Tablestore, teoricamente a Score b de cada linha retornada será superior à Score a.

    Esses resultados indicam que o baixo desempenho da consulta vetorial KNN decorre da qualidade insuficiente do modelo de Embedding na geração de vetores. A resposta inclui dados vetoriais com pontuação acima do esperado, enquanto dados com pontuação inferior ao esperado deixam de ser retornados.

  4. Escolha uma solução.

    Geralmente, esse problema ocorre em campos especializados. Por exemplo, modelos de Embedding genéricos podem não gerar vetores adequados para termos das indústrias de biotecnologia e medicina. Certos termos possuem semântica similar em contextos específicos, mas significados muito distintos em modelos gerais. Nessas situações, considere as seguintes abordagens:

    • Adote modelos de Embedding dedicados a domínios específicos.

      O ModelScope oferece diversos modelos de Embedding. Selecione um modelo voltado para sua área de atuação, como serviço público, e-commerce, saúde, justiça ou finanças, conforme suas necessidades de negócio. Para mais detalhes, consulte Lista de modelos de Embedding.

    • Colete um grande volume de corpus especializado por meios legais para treinar um modelo de Embedding adequado.

Apêndice: Código de exemplo das fórmulas de pontuação da consulta vetorial KNN

O código Java abaixo exemplifica como aplicar as fórmulas de pontuação dos algoritmos de medição de distância:

import java.util.concurrent.ThreadLocalRandom;

public class CompareVector {

    public static void main(String[] args) {
        // Specify a as the vector that you want to query.
        float[] a = randomVector(512);
        // Specify b as the vector that you expect the returned row to include.
        float[] b = randomVector(512);
        // Specify the similarity measurement algorithm that you configured in the search index to generate a score.
        System.out.println(MetricFunction.COSINE.compare(a, b));
    }

    public static float[] randomVector(int dim) {
        float[] vec = new float[dim];
        for (int i = 0; i < dim; i++) {
            vec[i] = ThreadLocalRandom.current().nextFloat();
            if (ThreadLocalRandom.current().nextBoolean()) {
                vec[i] = -vec[i];
            }
        }
        return l2normalize(vec, true);
    }

    public static float[] l2normalize(float[] v, boolean throwOnZero) {
        double squareSum = 0.0f;
        int dim = v.length;
        for (float x : v) {
            squareSum += x * x;
        }
        if (squareSum == 0) {
            if (throwOnZero) {
                throw new IllegalArgumentException("normalize a zero-length vector");
            } else {
                return v;
            }
        }
        double length = Math.sqrt(squareSum);
        for (int i = 0; i < dim; i++) {
            v[i] /= length;
        }
        return v;
    }

    public enum MetricFunction {
        /**
         * Euclidean distance.
         */
        EUCLIDEAN {
            @Override
            public float compare(float[] v1, float[] v2) {
                return 1 / (1 + VectorUtil.squareDistance(v1, v2));
            }
        },

        /**
         * Dot product.
         */
        DOT_PRODUCT {
            @Override
            public float compare(float[] v1, float[] v2) {
                return (1 + VectorUtil.dotProduct(v1, v2)) / 2;
            }
        },

        /**
         * Cosine.
         */
        COSINE {
            @Override
            public float compare(float[] v1, float[] v2) {
                return (1 + VectorUtil.cosine(v1, v2)) / 2;
            }
        };

        public abstract float compare(float[] v1, float[] v2);
    }

    static final class VectorUtil {

        private static void checkParam(float[] a, float[] b) {
            if (a.length != b.length) {
                throw new IllegalArgumentException("vector dimensions differ: " + a.length + "!=" + b.length);
            }
        }

        public static float dotProduct(float[] a, float[] b) {
            checkParam(a, b);
            float res = 0f;
            for (int i = 0; i < a.length; i++) {
                res += b[i] * a[i];
            }
            return res;
        }

        public static float cosine(float[] a, float[] b) {
            checkParam(a, b);
            float sum = 0.0f;
            float norm1 = 0.0f;
            float norm2 = 0.0f;
            for (int i = 0; i < a.length; i++) {
                float elem1 = a[i];
                float elem2 = b[i];
                sum += elem1 * elem2;
                norm1 += elem1 * elem1;
                norm2 += elem2 * elem2;
            }
            return (float) (sum / Math.sqrt((double) norm1 * (double) norm2));
        }

        public static float squareDistance(float[] a, float[] b) {
            checkParam(a, b);
            float sum = 0.0f;
            for (int i = 0; i < a.length; i++) {
                float difference = a[i] - b[i];
                sum += difference * difference;
            }
            return sum;
        }
    }
}