Todos os produtos
Search
Central de documentação

Tablestore:Otimize o desempenho da recuperação de vetores no Tablestore

Última atualização: Sep 08, 2026

O Tablestore usa o recurso de índice de busca para fornecer recuperação de vetores. Com esse recurso, você encontra os itens mais semelhantes em grandes conjuntos de dados. Se os resultados da recuperação de vetores para busca semântica não forem satisfatórios, consulte este tópico para otimizar o desempenho.

Fórmulas de pontuação da recuperação de vetores

Nota

A recuperação de vetores do Tablestore (KnnVectorQuery) usa vetores numéricos para executar consultas aproximadas de vizinhos mais próximos. Essa funcionalidade é adequada para cenários como geração aumentada por recuperação (RAG), sistemas de recomendação, detecção de similaridade, processamento de linguagem natural e busca semântica. Para obter mais informações sobre como usar a recuperação de vetores, consulte Vector retrieval.

A recuperação de vetores oferece suporte às medidas de distância euclidiana (euclidean), similaridade de cosseno (cosine) e produto escalar (dot_product). Cada medida possui uma fórmula de pontuação distinta que o Tablestore aplica para avaliar a similaridade entre vetores. A tabela a seguir descreve essas fórmulas.

MetricType

Fórmula de pontuação

Distância euclidiana (euclidean)

image

Produto escalar (dot_product)

image

Similaridade de cosseno (cosine)

image

Solução de problemas e análise

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

Na recuperação de vetores, ordene os resultados por pontuação com ScoreSort. Por padrão, a ordenação ocorre pela chave primária.

2. Ajuste o uso do BoolQuery

Ao combinar KnnVectorQuery (recuperação de vetores) com BoolQuery (consulta multicondicional), defina o tipo de consulta do índice de busca como KnnVectorQuery e adicione as condições da BoolQuery ao parâmetro Filter (filtro de recuperação de vetores). Esse método não afeta o cálculo da pontuação.

Importante

Se você definir o tipo de consulta como BoolQuery e usar KnnVectorQuery como subcondição, outras condições na BoolQuery poderão afetar o cálculo da pontuação. Para obter mais informações, consulte Usage with BoolQuery.

O código Java a seguir apresenta um exemplo de recuperação de vetores.

private static void knnVectorQuery(SyncClient client) {
    SearchQuery searchQuery = new SearchQuery();
    KnnVectorQuery query = new KnnVectorQuery();
    query.setFieldName("Col_Vector");
    query.setTopK(10); // Return the top K nearest neighbors.
    query.setFloat32QueryVector(new float[]{0.1f, 0.2f, 0.3f, 0.4f});
    // The nearest neighbor vectors must meet the condition: Col_Keyword=hangzhou && Col_Long<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 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);
    // Access the Search interface.
    SearchResponse resp = client.search(searchRequest);
    for (SearchHit hit : resp.getSearchHits()) {
        // Print the score.
        System.out.println(hit.getScore());
        // Print the data.
        System.out.println(hit.getRow());
    }
}

3. Verifique a qualidade da geração de vetores

O Tablestore calcula a similaridade dos dados vetoriais, mas não avalia a qualidade da geração desses vetores. Um modelo de embedding externo gera tanto os vetores no banco de dados quanto os vetores de consulta. Em cenários altamente especializados, os vetores gerados podem ser ineficazes. Para solucionar esse problema, siga estas etapas:

  1. Calcule a pontuação diretamente sem usar o Tablestore.

    1. Defina o vetor de consulta como vector a e o vetor a recuperar da tabela do Tablestore como vector b.

      Nota

      Obtenha os dados do vector b pelas APIs de leitura de índice de busca, índice secundário ou tabela ampla.

    2. Calcule a score a com o método MetricFunction.COSINE.compare(a, b). Esse método está disponível no código de demonstração em Appendix: Demo code for vector retrieval scoring formulas.

  2. Calcule a pontuação usando o Tablestore.

    Use o recurso de recuperação de vetores do Tablestore para consultar o vector a. Em seguida, verifique a score b de cada linha nos resultados retornados.

  3. Análise comparativa

    Se os resultados da recuperação de vetores do Tablestore não incluírem a linha com o vector b, a score b de cada linha retornada será, teoricamente, superior à score a.

    Esse resultado confirma que a insatisfação com a recuperação decorre do baixo desempenho do modelo de embedding. A recuperação contém apenas dados vetoriais com pontuações superiores ao resultado esperado, razão pela qual o resultado desejado não foi retornado.

  4. Soluções recomendadas

    Esse problema geralmente ocorre em domínios especializados. Por exemplo, termos específicos da biomedicina podem ter baixo desempenho com um modelo de embedding de uso geral. O modelo pode não interpretar como semanticamente semelhantes termos que são similares em um domínio específico. Nessas situações, considere as seguintes soluções:

    • Busque um modelo de embedding específico para o seu domínio.

      O ModelScope oferece diversos modelos de embedding prontos para uso. Escolha modelos voltados para domínios especializados, como governo, comércio eletrônico, saúde, direito e finanças. Para obter mais informações, consulte Lista de modelos de embedding.

    • Colete um grande volume de corpus profissional e use esses dados para treinar um modelo de embedding adequado.

Apêndice: Código de demonstração das fórmulas de pontuação da recuperação de vetores

O código Java a seguir demonstra as fórmulas de pontuação para as medidas de distância suportadas.

import java.util.concurrent.ThreadLocalRandom;

public class CompareVector {

    public static void main(String[] args) {
        // a is the query vector
        float[] a = randomVector(512);
        // b is the vector from the row in the index that you expect to be returned
        float[] b = randomVector(512);
        // Select the similarity measure algorithm that you set in your search index and output the 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;
        }
    }
}