Menyesuaikan performa kueri vektor

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

Menyesuaikan indeks ScaNN

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

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

Sebelum membuat indeks ScaNN, selesaikan langkah-langkah berikut:

  • Pastikan tabel dengan data Anda sudah dibuat.
  • Pastikan nilai yang Anda tetapkan untuk flag 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 recall 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 meningkatkan partisi untuk sejumlah vektor yang ditetapkan, Anda akan membuat indeks yang lebih terperinci, yang meningkatkan performa kueri dan recall. Namun, hal ini akan memperpanjang waktu pembuatan indeks.

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

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

    Karena indeks hierarki dua tingkat dapat dibuat pada set data dengan kurang dari 10 juta baris vektor, setiap partisi akan menyimpan kurang dari (sqrt(10M)) vektor, yaitu vektor 3200. 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 untuk memilih nilai yang tepat, gunakan power(ROWS, 2/3) sebagai titik awal, dengan ROWS adalah jumlah baris vektor. Jumlah vektor yang disimpan setiap partisi dihitung oleh
    ROWS/power(ROWS, 2/3) = power(ROWS, 1/3).

    Karena indeks hierarki 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 quantizer yang ingin Anda gunakan untuk hierarki K-means. Nilai default-nya adalah SQ8 untuk performa kueri yang lebih baik.

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

Tetapkan ke false jika Anda mengamati penurunan dalam recall.
Pembuatan indeks
scann.num_leaves_to_search Flag database mengontrol kompromi antara recall dan QPS. Nilai defaultnya adalah 1% dari nilai yang ditetapkan di num_leaves.

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

Makin tinggi nilai yang ditetapkan, makin baik QPS dalam kueri yang difilter, tetapi akan menghasilkan penggunaan memori yang lebih tinggi, dan sebaliknya.
Runtime kueri
scann.pre_reordering_num_neighbors Tanda database saat ditetapkan, menentukan jumlah kandidat tetangga yang akan dipertimbangkan selama tahap pengurutan ulang setelah penelusuran awal mengidentifikasi sekumpulan kandidat. Tetapkan nilai ini ke nilai yang lebih tinggi dari jumlah tetangga yang ingin ditampilkan kueri.

Set nilai yang lebih tinggi menghasilkan recall yang lebih baik, tetapi pendekatan ini menghasilkan QPS yang lebih rendah.
Runtime kueri
max_num_levels Jumlah maksimum level hierarki pengelompokan K-means.
  • Indeks hierarki dua tingkat: Ditetapkan secara default untuk kuantisasi berbasis hierarki dua tingkat.
  • Indeks hierarki tiga tingkat: Tetapkan 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 menetapkan parameter penyesuaian:

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 pembaruan pada tabel tempat indeks ScaNN sudah dibuat akan memengaruhi cara hierarki yang dipelajari mengoptimalkan indeks. Jika tabel Anda rentan terhadap pembaruan atau penyisipan yang sering, sebaiknya indeks ScaNN yang ada diindeks ulang secara berkala untuk meningkatkan akurasi recall.

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

Praktik terbaik untuk penyesuaian

Berdasarkan jenis indeks ScaNN yang ingin 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 guna membantu Anda menemukan nilai num_leaves dan num_leaves_to_search yang optimal untuk set data, ikuti langkah-langkah berikut:

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

    Jika Anda menggunakan vektor dimensi tinggi (500 dimensi atau lebih tinggi) dan ingin meningkatkan recall, 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 mencapai recall 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 nilainya sudah dua kali lipat, coba tetapkan nilai tersebut untuk melipatgandakan akar kuadrat.
      • Tingkatkan scann.num_leaves_to_search sesuai kebutuhan untuk mempertahankan rasionya dengan num_leaves, yang Anda catat pada Langkah 3.
      • Tetapkan num_leaves ke nilai yang kurang dari atau sama dengan jumlah baris dibagi 100.
    2. Jalankan lagi kueri pengujian. Saat menjalankan kueri pengujian, lakukan eksperimen dengan mengurangi scann.num_leaves_to_search, menemukan nilai yang meningkatkan QPS sekaligus menjaga perolehan tetap tinggi. Coba nilai scann.num_leaves_to_search yang berbeda tanpa membuat ulang indeks.
  5. Ulangi Langkah 4 hingga QPS dan rentang recall mencapai nilai yang dapat diterima.

Indeks hierarki tiga tingkat

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

  • Meningkatkan max_num_levels dari 1 untuk hierarki dua tingkat menjadi 2 untuk hierarki tiga tingkat secara signifikan mengurangi waktu untuk membuat indeks, tetapi mengorbankan akurasi recall. 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 antara 10 juta dan 100 juta baris, berdasarkan keseimbangan waktu pembuatan indeks dan akurasi recall 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 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 cara menganalisis kueri, lihat Menganalisis kueri.

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

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

    • Jika nilai max_num_levels adalah 1, hapus indeks. Buat ulang indeks dengan nilai max_num_levels yang ditetapkan ke 2.

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

    • Jika nilai max_num_levels adalah 2, hapus indeks. Buat ulang indeks dengan nilai max_num_levels yang sama dan sesuaikan nilai num_leaves untuk akurasi recall 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 maksimal satu juta baris, dan sqrt(rows) untuk lebih dari satu juta baris. Pembuatan indeks
quantizer Jenis quantizer yang ingin Anda gunakan untuk hierarki K-means. Nilai defaultnya adalah SQ8 untuk performa kueri yang lebih baik. Tetapkan ke FLAT untuk recall yang lebih baik. Pembuatan indeks
ivf.probes jumlah daftar terdekat yang akan dijelajahi selama penelusuran. Titik awal untuk nilai ini adalah
sqrt(lists).
Runtime 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 dan ivfflat.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 maksimal satu juta baris, dan sqrt(rows) untuk lebih dari satu juta baris. Pembuatan indeks
ivfflat.probes Jumlah daftar terdekat yang akan dijelajahi selama penelusuran. Titik awal untuk nilai ini adalah
sqrt(lists).
Runtime kueri

Sebelum mem-build indeks IVFFlat, pastikan flag max_parallel_maintenance_workers database Anda ditetapkan ke nilai yang memadai 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 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 node. Tetapkan nilai ini ke nilai apa pun 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 menetapkan nilai ini ke m atau ef_construction, lalu mengubahnya sambil mengamati recall. Nilai defaultnya adalah 40. Runtime 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

Gunakan perintah EXPLAIN ANALYZE untuk menganalisis insight kueri 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;

Contoh respons QUERY PLAN menyertakan 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 informasi selengkapnya tentang daftar lengkap metrik, lihat Metrik indeks vektor.

Langkah selanjutnya