Menyesuaikan performa kueri vektor

Pilih versi dokumentasi:

Dokumen ini menunjukkan cara menyesuaikan indeks untuk mencapai performa kueri yang lebih cepat dan perolehan yang lebih baik.

Menyesuaikan indeks ScaNN

Indeks ScaNN menggunakan pengindeksan berbasis kuantisasi pohon. Dalam teknik Kuantisasi pohon, indeks mempelajari pohon penelusuran bersama dengan fungsi kuantisasi (atau hashing). Saat Anda menjalankan kueri, pohon penelusuran digunakan untuk memangkas ruang penelusuran, sedangkan kuantisasi digunakan untuk mengompresi ukuran indeks. Pemangkasan ini mempercepat pemberian skor kesamaan (yaitu, jarak) antara vektor kueri dan vektor database.

Untuk mencapai rasio kueri per detik (QPS) yang tinggi dan perolehan yang tinggi dengan kueri nearest neighbor, Anda harus mempartisi hierarki indeks ScaNN dengan cara yang paling sesuai untuk data dan kueri Anda.

Sebelum Anda membuat indeks ScaNN, selesaikan langkah-langkah berikut:

  • Pastikan tabel dengan data Anda sudah dibuat.
  • Pastikan nilai yang Anda tetapkan untuk tanda maintenance_work_mem dan shared_buffers kurang dari total memori mesin untuk menghindari masalah saat membuat indeks.

Parameter penyempurnaan

Parameter indeks dan tanda database berikut digunakan bersama untuk menemukan keseimbangan yang tepat antara perolehan dan QPS. Semua parameter berlaku untuk kedua jenis indeks ScaNN.

Parameter penyesuaian Deskripsi Jenis parameter
num_leaves Jumlah partisi yang akan diterapkan ke indeks ini. Jumlah partisi yang Anda terapkan saat membuat indeks memengaruhi performa indeks. Dengan menambah partisi untuk sejumlah vektor, Anda membuat indeks yang lebih terperinci, yang meningkatkan perolehan dan performa kueri. Namun, hal ini akan menyebabkan waktu pembuatan indeks yang lebih lama.

Karena pohon tiga tingkat dibuat lebih cepat daripada pohon dua tingkat, Anda dapat meningkatkan num_leaves_value saat membuat indeks pohon tiga tingkat untuk mencapai performa yang lebih baik.
  • Indeks dua tingkat: Tetapkan nilai ini ke nilai apa pun antara 1 dan 1048576.

    Jika Anda tidak yakin dalam memilih nilai yang tepat, gunakan sqrt(ROWS) sebagai titik awal, dengan ROWS adalah jumlah baris vektor. Jumlah vektor yang dimiliki setiap partisi dihitung oleh
    ROWS/sqrt(ROWS) = sqrt(ROWS).

    Karena indeks pohon dua tingkat dapat dibuat pada set data dengan kurang dari 10 juta baris vektor, setiap partisi akan menyimpan kurang dari (sqrt(10M)) vektor, yaitu 3200 vektor. Untuk performa yang optimal, sebaiknya minimalkan jumlah vektor di setiap partisi.
  • Indeks tiga tingkat: Tetapkan nilai ini ke nilai apa pun antara 1 dan 1048576.

    Jika Anda tidak yakin dalam memilih nilai yang tepat, gunakan power(ROWS, 2/3) sebagai titik awal, dengan ROWS adalah jumlah baris vektor. Jumlah vektor yang dimiliki setiap partisi dihitung oleh
    ROWS/power(ROWS, 2/3) = power(ROWS, 1/3).

    Karena indeks pohon tiga tingkat dapat dibuat pada set data dengan baris vektor lebih dari 100 juta, setiap partisi akan menyimpan lebih dari
    (power(100M, 1/3)) vektor, yaitu 465 vektor. Untuk performa yang optimal, sebaiknya minimalkan jumlah vektor di setiap partisi.
Pembuatan indeks
quantizer Jenis penguantisasi yang ingin Anda gunakan untuk pohon K-means. Nilai defaultnya adalah SQ8 untuk performa kueri yang lebih baik.

Tetapkan ke FLAT untuk mengingat kembali yang lebih baik.
Pembuatan indeks
enable_pca Mengaktifkan Analisis Komponen Utama (PCA), yang merupakan teknik pengurangan dimensi yang digunakan untuk secara otomatis mengurangi ukuran embedding jika memungkinkan. Opsi ini diaktifkan secara default.

Setel ke false jika Anda melihat penurunan kualitas ingatan.
Pembuatan indeks
scann.num_leaves_to_search Flag database mengontrol keseimbangan antara recall dan QPS. Nilai defaultnya adalah 1% dari nilai yang ditetapkan di num_leaves.

Makin tinggi nilai yang ditetapkan, makin baik perolehannya, tetapi menghasilkan QPS yang lebih rendah, dan sebaliknya.
Waktu proses kueri
scann.max_top_neighbors_buffer_size Flag database menentukan ukuran cache yang digunakan untuk meningkatkan performa kueri yang difilter dengan memberi skor atau memberi peringkat pada kandidat tetangga yang dipindai dalam memori, bukan disk. Nilai defaultnya adalah 20000.

Semakin tinggi nilai yang ditetapkan, semakin baik QPS di bawah kueri yang difilter, tetapi menghasilkan penggunaan memori yang lebih tinggi, dan sebaliknya.
Waktu proses kueri
scann.pre_reordering_num_neighbors Jika disetel, tanda database menentukan jumlah tetangga kandidat yang akan dipertimbangkan selama tahap pengurutan ulang setelah penelusuran awal mengidentifikasi sekumpulan kandidat. Tetapkan ini ke nilai yang lebih tinggi daripada jumlah tetangga yang ingin Anda tampilkan oleh kueri.

Kumpulan nilai yang lebih tinggi menghasilkan perolehan yang lebih baik, tetapi pendekatan ini menghasilkan QPS yang lebih rendah.
Waktu proses kueri
max_num_levels Jumlah maksimum level pohon pengelompokan K-means.
  • Indeks pohon dua tingkat: Disetel secara default untuk kuantisasi berbasis pohon dua tingkat.
  • Indeks hierarki tiga tingkat: Setel ke 2 secara eksplisit untuk kuantisasi berbasis hierarki tiga tingkat.
Pembuatan indeks

Menyesuaikan indeks ScaNN

Pertimbangkan contoh berikut untuk indeks ScaNN dua tingkat dan tiga tingkat yang menunjukkan cara parameter penyesuaian ditetapkan:

Indeks dua tingkat

SET LOCAL scann.num_leaves_to_search = 1;
SET LOCAL scann.pre_reordering_num_neighbors=50;

CREATE INDEX my-scann-index ON my-table
  USING scann (vector_column cosine)
  WITH (num_leaves = [power(1000000, 1/2)]);

Indeks tiga tingkat

SET LOCAL scann.num_leaves_to_search = 10;
SET LOCAL scann.pre_reordering_num_neighbors=50;

CREATE INDEX my-scann-index ON my-table
  USING scann (vector_column cosine)
  WITH (num_leaves = [power(1000000, 2/3)], max_num_levels = 2);

Setiap operasi penyisipan atau update pada tabel tempat indeks ScaNN sudah dibuat akan memengaruhi cara pohon yang dipelajari mengoptimalkan indeks. Jika tabel Anda sering diupdate atau disisipkan, sebaiknya indeks ulang indeks ScaNN yang ada secara berkala untuk meningkatkan akurasi perolehan.

Anda dapat memantau metrik indeks untuk menentukan jumlah mutasi yang dibuat sejak indeks dibuat, lalu mengindeks ulang sesuai kebutuhan. Untuk mengetahui informasi selengkapnya tentang metrik, lihat Metrik indeks vektor.

Praktik terbaik untuk penyesuaian

Bergantung pada jenis indeks ScaNN yang akan Anda gunakan, rekomendasi untuk menyesuaikan indeks Anda akan bervariasi. Bagian ini memberikan rekomendasi tentang cara menyesuaikan parameter indeks untuk mendapatkan keseimbangan yang optimal antara recall dan QPS.

Indeks hierarki dua tingkat

Untuk menerapkan rekomendasi yang membantu Anda menemukan nilai num_leaves dan num_leaves_to_search yang optimal untuk set data Anda, ikuti langkah-langkah berikut:

  1. Buat indeks ScaNN dengan num_leaves yang ditetapkan ke akar kuadrat jumlah baris tabel yang diindeks.
  2. Jalankan kueri pengujian, dengan meningkatkan nilai scann.num_of_leaves_to_search, hingga Anda mencapai rentang perolehan target–misalnya, 95%. Untuk mengetahui informasi selengkapnya tentang menganalisis kueri, lihat Menganalisis kueri.
  3. Catat rasio antara scann.num_leaves_to_search dan num_leaves yang akan digunakan pada langkah-langkah berikutnya. Rasio ini memberikan perkiraan seputar set data yang akan membantu Anda mencapai target perolehan.

    Jika Anda bekerja dengan vektor dimensi tinggi (500 dimensi atau lebih) dan ingin meningkatkan perolehan, coba sesuaikan nilai scann.pre_reordering_num_neighbors. Sebagai titik awal, tetapkan nilai ke 100 * sqrt(K) dengan K adalah batas yang Anda tetapkan dalam kueri.
  4. Jika QPS Anda terlalu rendah setelah kueri Anda mencapai perolehan target, ikuti langkah-langkah berikut:
    1. Buat ulang indeks, dengan meningkatkan nilai num_leaves dan scann.num_leaves_to_search sesuai panduan berikut:
      • Tetapkan num_leaves ke faktor yang lebih besar dari akar kuadrat jumlah baris Anda. Misalnya, jika indeks memiliki num_leaves yang ditetapkan ke akar kuadrat jumlah baris, coba tetapkan ke dua kali akar kuadrat. Jika nilai sudah ganda, coba tetapkan ke tiga kali akar kuadrat.
      • Tingkatkan scann.num_leaves_to_search sesuai kebutuhan untuk mempertahankan rasionya dengan num_leaves, yang Anda catat di Langkah 3.
      • Tetapkan num_leaves ke nilai yang kurang dari atau sama dengan jumlah baris dibagi 100.
    2. Jalankan kueri pengujian lagi. Saat Anda menjalankan kueri pengujian, lakukan eksperimen dengan mengurangi scann.num_leaves_to_search, temukan nilai yang meningkatkan QPS sekaligus mempertahankan perolehan yang tinggi. Coba nilai scann.num_leaves_to_search yang berbeda tanpa membangun ulang indeks.
  5. Ulangi Langkah 4 hingga QPS dan rentang perolehan mencapai nilai yang dapat diterima.

Indeks hierarki tiga tingkat

Selain rekomendasi untuk indeks pohon ScaNN dua tingkat, gunakan panduan dan langkah-langkah berikut untuk menyesuaikan indeks:

  • Meningkatkan max_num_levels dari 1 untuk pohon dua tingkat menjadi 2 untuk pohon tiga tingkat secara signifikan mengurangi waktu pembuatan indeks, tetapi dengan mengorbankan akurasi perolehan. Tetapkan max_num_levels menggunakan rekomendasi berikut:
    • Tetapkan nilai ke 2 jika jumlah baris vektor melebihi 100 juta baris.
    • Tetapkan nilai ke 1 jika jumlah baris vektor kurang dari 10 juta baris.
    • Tetapkan ke 1 atau 2 jika jumlah baris vektor berada di antara 10 juta dan 100 juta baris, berdasarkan keseimbangan waktu pembuatan indeks dan akurasi perolehan yang Anda butuhkan.

Untuk menerapkan rekomendasi guna menemukan nilai optimal parameter indeks num_leaves dan max_num_levels, ikuti langkah-langkah berikut:

  1. Buat indeks ScaNN dengan kombinasi num_leaves dan max_num_levels berikut berdasarkan set data Anda:

    • baris vektor yang lebih dari 100 juta baris: Tetapkan max_num_levels sebagai 2 dan num_leaves sebagai power(rows, ⅔).
    • baris vektor kurang dari 100 juta baris: Tetapkan max_num_levels sebagai 1 dan num_leaves sebagai sqrt(rows).
    • baris vektor antara 10 juta dan 100 juta baris: Mulailah dengan menetapkan max_num_levels sebagai 1 dan num_leaves sebagai sqrt(rows).
  2. Jalankan kueri pengujian Anda. Untuk mengetahui informasi selengkapnya tentang menganalisis kueri, lihat Menganalisis kueri.

    Jika waktu pembuatan indeks memuaskan, pertahankan nilai max_num_levels, dan bereksperimenlah dengan nilai num_leaves untuk akurasi perolehan yang optimal.

  3. Jika Anda tidak puas dengan waktu pembuatan indeks, lakukan hal berikut:

    • Jika nilai max_num_levels adalah 1, hapus indeks. Bangun kembali indeks dengan nilai max_num_levels yang ditetapkan ke 2.

      Jalankan kueri dan sesuaikan nilai num_leaves untuk akurasi perolehan yang optimal.

    • Jika nilai max_num_levels adalah 2, hapus indeks. Bangun ulang indeks dengan nilai max_num_levels yang sama dan sesuaikan nilai num_leaves untuk akurasi perolehan yang optimal.

Menyesuaikan indeks IVF

Menyesuaikan nilai yang Anda tetapkan untuk parameter lists, ivf.probes, dan quantizer dapat membantu mengoptimalkan performa aplikasi Anda:

Parameter penyesuaian Deskripsi Jenis parameter
lists Jumlah daftar yang dibuat selama pembuatan indeks. Titik awal untuk menetapkan nilai ini adalah (rows)/1000 untuk hingga satu juta baris, dan sqrt(rows) untuk lebih dari satu juta baris. Pembuatan indeks
quantizer Jenis penguantisasi yang ingin Anda gunakan untuk pohon K-means. Nilai defaultnya adalah SQ8 untuk performa kueri yang lebih baik. Tetapkan ke FLAT agar lebih mudah diingat. Pembuatan indeks
ivf.probes jumlah daftar terdekat yang dapat dijelajahi selama penelusuran. Titik awal untuk nilai ini adalah
sqrt(lists).
Waktu proses kueri

Pertimbangkan contoh berikut yang menunjukkan indeks IVF dengan parameter penyesuaian yang ditetapkan:

SET LOCAL ivf.probes = 10;

CREATE INDEX my-ivf-index ON my-table
  USING ivf (vector_column cosine)
  WITH (lists = 100, quantizer = 'SQ8');

Menyesuaikan indeks IVFFlat

Menyesuaikan nilai yang Anda tetapkan untuk parameter lists danivfflat.probes dapat membantu mengoptimalkan performa aplikasi:

Parameter penyesuaian Deskripsi Jenis parameter
lists Jumlah daftar yang dibuat selama pembuatan indeks. Titik awal untuk menetapkan nilai ini adalah (rows)/1000 untuk hingga satu juta baris, dan sqrt(rows) untuk lebih dari satu juta baris. Pembuatan indeks
ivfflat.probes Jumlah daftar terdekat yang dapat dijelajahi selama penelusuran. Titik awal untuk nilai ini adalah
sqrt(lists).
Waktu proses kueri

Sebelum membuat indeks IVFFlat, pastikan tanda max_parallel_maintenance_workers database Anda ditetapkan ke nilai yang cukup untuk mempercepat pembuatan indeks pada tabel besar.

Pertimbangkan contoh berikut yang menunjukkan indeks IVFFlat dengan parameter penyesuaian yang ditetapkan:

SET LOCAL ivfflat.probes = 10;

CREATE INDEX my-ivfflat-index ON my-table
  USING ivfflat (vector_column cosine)
  WITH (lists = 100);

Menyesuaikan indeks HNSW

Menyesuaikan nilai yang Anda tetapkan untuk parameter m, ef_construction, dan hnsw.ef_search dapat membantu mengoptimalkan performa aplikasi.

Parameter penyesuaian Deskripsi Jenis parameter
m Jumlah maksimum koneksi per dari node dalam grafik. Anda dapat memulai dengan nilai default sebagai 16(default) dan bereksperimen dengan nilai yang lebih tinggi berdasarkan ukuran set data Anda. Pembuatan indeks
ef_construction Ukuran daftar kandidat dinamis yang dipertahankan selama konstruksi grafik, yang terus memperbarui kandidat terbaik saat ini untuk tetangga terdekat untuk sebuah node. Tetapkan nilai ini ke nilai yang lebih tinggi dari dua kali nilai m—misalnya, 64(default). Pembuatan indeks
ef_search Ukuran daftar kandidat dinamis yang digunakan selama penelusuran. Anda dapat mulai menyetel nilai ini ke m atau ef_construction, lalu mengubahnya sambil mengamati ingatan. Nilai defaultnya adalah 40. Waktu proses kueri

Pertimbangkan contoh berikut yang menunjukkan indeks hnsw dengan parameter penyesuaian yang ditetapkan:

SET LOCAL hnsw.ef_search = 40;

CREATE INDEX my-hnsw-index ON my-table
  USING hnsw (vector_column cosine)
  WITH (m = 16, ef_construction = 200);

Menganalisis kueri Anda

Gunakan perintah EXPLAIN ANALYZE untuk menganalisis insight kueri Anda seperti yang ditunjukkan dalam contoh kueri SQL berikut.

  EXPLAIN ANALYZE SELECT result-column FROM my-table
    ORDER BY EMBEDDING_COLUMN ::vector
    USING INDEX my-scann-index
    <-> embedding('textembedding-gecko@003', 'What is a database?')
    LIMIT 1;

Respons contoh QUERY PLAN mencakup informasi seperti waktu yang diperlukan, jumlah baris yang dipindai atau ditampilkan, dan resource yang digunakan.

Limit  (cost=0.42..15.27 rows=1 width=32) (actual time=0.106..0.132 rows=1 loops=1)
  ->  Index Scan using my-scann-index on my-table  (cost=0.42..858027.93 rows=100000 width=32) (actual time=0.105..0.129 rows=1 loops=1)
        Order By: (embedding_column <-> embedding('textgecko@003', 'What is a database?')::vector(768))
        Limit value: 1
Planning Time: 0.354 ms
Execution Time: 0.141 ms

Melihat metrik indeks vektor

Anda dapat menggunakan metrik indeks vektor untuk meninjau performa indeks vektor, mengidentifikasi area yang perlu ditingkatkan, dan menyesuaikan indeks berdasarkan metrik, jika diperlukan.

Untuk melihat semua metrik indeks vektor, jalankan kueri SQL berikut, yang menggunakan tampilan pg_stat_ann_indexes:

SELECT * FROM pg_stat_ann_indexes;

Untuk mengetahui informasi selengkapnya tentang daftar lengkap metrik, lihat Metrik indeks vektor.

Langkah berikutnya