All Products
Search
Document Center

Tablestore:Optimalkan kinerja pengambilan vektor di Tablestore

Last Updated:Sep 09, 2026

Tablestore menggunakan fitur indeks pencarian untuk menyediakan pengambilan vektor. Fitur ini memungkinkan Anda menemukan item data yang paling mirip dalam set data besar. Jika hasil pengambilan vektor untuk pencarian semantik tidak memuaskan, rujuk topik ini untuk mengoptimalkan kinerjanya.

Rumus penilaian pengambilan vektor

Catatan

Tablestore menggunakan pengambilan vektor (KnnVectorQuery) berbasis vektor numerik untuk menjalankan kueri tetangga terdekat aproksimasi. Fitur ini cocok untuk skenario seperti Generasi yang Diperkaya dengan Pengambilan Data (RAG), sistem rekomendasi, deteksi kemiripan, pemrosesan bahasa alami, dan pencarian semantik. Untuk informasi lebih lanjut tentang cara menggunakan pengambilan vektor, lihat Pengambilan vektor.

Pengambilan vektor mendukung tiga ukuran jarak: Jarak Euclidean (euclidean), kemiripan kosinus (cosine), dan hasil kali titik (dot_product). Setiap ukuran jarak memiliki rumus penilaian yang berbeda, yang digunakan Tablestore untuk mengevaluasi kemiripan antar vektor. Tabel berikut menjelaskan rumus-rumus tersebut.

MetricType

Rumus penilaian

Jarak Euclidean (euclidean)

image

Hasil kali titik (dot_product)

image

Kemiripan kosinus (cosine)

image

Pemecahan masalah dan analisis

1. Periksa metode pengurutan

Saat menggunakan pengambilan vektor, Anda dapat mengurutkan hasil berdasarkan skor dengan ScoreSort. Secara default, hasil diurutkan berdasarkan kunci primer.

2. Atur cara penggunaan BoolQuery

Jika Anda menggabungkan KnnVectorQuery (pengambilan vektor) dengan BoolQuery (kueri multi-kondisional), atur jenis kueri indeks pencarian ke KnnVectorQuery dan tambahkan kondisi BoolQuery ke parameter Filter (filter pengambilan vektor). Pendekatan ini tidak memengaruhi perhitungan skor.

Penting

Jika Anda mengatur jenis kueri ke BoolQuery dan menggunakan KnnVectorQuery sebagai sub-kondisi, kondisi kueri lain dalam BoolQuery dapat memengaruhi perhitungan skor. Untuk informasi lebih lanjut, lihat Penggunaan dengan BoolQuery.

Kode Java berikut memberikan contoh pengambilan vektor.

private static void knnVectorQuery(SyncClient client) {
    SearchQuery searchQuery = new SearchQuery();
    KnnVectorQuery query = new KnnVectorQuery();
    query.setFieldName("Col_Vector");
    query.setTopK(10); // Mengembalikan K tetangga terdekat teratas.
    query.setFloat32QueryVector(new float[]{0.1f, 0.2f, 0.3f, 0.4f});
    // Vektor tetangga terdekat harus memenuhi kondisi: 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);
    // Urutkan berdasarkan skor.
    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);
    // Akses antarmuka Search.
    SearchResponse resp = client.search(searchRequest);
    for (SearchHit hit : resp.getSearchHits()) {
        // Cetak skor.
        System.out.println(hit.getScore());
        // Cetak data.
        System.out.println(hit.getRow());
    }
}

3. Periksa kualitas pembuatan vektor

Tablestore menghitung kemiripan antar data vektor, tetapi tidak mengevaluasi kualitas pembuatan vektor itu sendiri. Vektor dalam database maupun vektor kueri dihasilkan oleh model penyematan eksternal. Dalam skenario yang sangat spesialis, vektor yang dihasilkan mungkin tidak efektif. Anda dapat memecahkan masalah ini sebagai berikut:

  1. Hitung skor secara langsung tanpa menggunakan Tablestore.

    1. Definisikan vektor kueri sebagai vektor a dan vektor yang ingin Anda ambil dari tabel Tablestore sebagai vektor b.

      Catatan

      Anda dapat memperoleh data untuk vektor b melalui API indeks pencarian, indeks sekunder, atau pembacaan data tabel lebar.

    2. Hitung skor a menggunakan metode MetricFunction.COSINE.compare(a, b), yang tersedia dalam kode demo di Lampiran: Kode demo untuk rumus penilaian pengambilan vektor.

  2. Hitung skor menggunakan Tablestore.

    Gunakan fitur pengambilan vektor Tablestore untuk mengkueri vektor a, lalu periksa skor b pada setiap baris dalam hasil yang dikembalikan.

  3. Analisis komparatif

    Jika hasil pengambilan vektor Tablestore tidak mencakup baris yang berisi vektor b, maka skor b untuk setiap baris yang dikembalikan secara teoretis lebih tinggi daripada skor a.

    Temuan ini mengonfirmasi bahwa hasil pengambilan vektor yang tidak memuaskan disebabkan oleh kinerja model penyematan yang buruk. Hasil pengambilan hanya berisi data vektor dengan skor lebih tinggi daripada hasil yang diharapkan, sehingga hasil yang diinginkan tidak dikembalikan.

  4. Solusi yang direkomendasikan

    Masalah ini umum terjadi dalam domain khusus. Misalnya, istilah tertentu dalam bidang biomedis mungkin tidak sesuai dengan model penyematan umum. Istilah yang secara semantik mirip dalam domain khusus mungkin tidak dianggap mirip oleh model tersebut. Dalam kasus ini, pertimbangkan solusi berikut:

    • Gunakan model penyematan yang dirancang khusus untuk domain Anda.

      ModelScope menyediakan berbagai model penyematan siap pakai untuk domain khusus seperti pemerintahan, E-dagang, kesehatan, hukum, dan keuangan. Untuk informasi lebih lanjut, lihat Daftar Model Penyematan.

    • Kumpulkan sejumlah besar data korpus profesional dan gunakan data tersebut untuk melatih model penyematan yang sesuai.

Lampiran: Kode demo untuk rumus penilaian pengambilan vektor

Kode Java berikut menunjukkan rumus penilaian untuk ukuran jarak yang didukung.

import java.util.concurrent.ThreadLocalRandom;

public class CompareVector {

    public static void main(String[] args) {
        // a adalah vektor kueri
        float[] a = randomVector(512);
        // b adalah vektor dari baris dalam indeks yang Anda harapkan dikembalikan
        float[] b = randomVector(512);
        // Pilih algoritma ukuran kemiripan yang Anda atur dalam indeks pencarian dan keluarkan skornya
        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 {
        /**
         * Jarak Euclidean.
         */
        EUCLIDEAN {
            @Override
            public float compare(float[] v1, float[] v2) {
                return 1 / (1 + VectorUtil.squareDistance(v1, v2));
            }
        },

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

        /**
         * Kosinus.
         */
        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;
        }
    }
}