Membuat indeks ScaNN

Gunakan embedding yang disimpan untuk membuat indeks vektor ScaNN dan kueri embedding dengan AlloyDB untuk PostgreSQL.

Indeks ScaNN adalah indeks kuantisasi berbasis hierarki buatan Google untuk penelusuran approximate nearest neighbor. Algoritma ini memberikan waktu pembuatan indeks yang lebih rendah dan jejak memori yang lebih kecil dibandingkan dengan HNSW. Selain itu, QPS yang dihasilkan lebih cepat dibandingkan dengan HNSW berdasarkan beban kerja.

Sebelum memulai

Sebelum dapat mulai membuat indeks, Anda harus menyelesaikan prasyarat berikut.

Membuat indeks yang disesuaikan secara otomatis

Indeks ScaNN yang disesuaikan secara otomatis menyederhanakan pembuatan indeks dengan memungkinkan AlloyDB mengelola dan menyesuaikan struktur indeks. Jika Anda memerlukan kontrol terperinci atas penyesuaian indeks, buat indeks ScaNN yang disesuaikan secara manual.

Indeks yang disesuaikan secara otomatis dapat dioptimalkan dengan dua cara:

  • (Default) Performa recall dan latensi penelusuran vektor dengan mengorbankan waktu pembuatan indeks
  • Menyeimbangkan waktu pembuatan indeks dan performa penelusuran

Untuk membuat indeks ScaNN yang disesuaikan secara otomatis, jalankan perintah berikut.

CREATE INDEX INDEX_NAME ON TABLE
       USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)

Ganti kode berikut:

  • INDEX_NAME: nama indeks yang ingin Anda buat. Contoh, my_scann_index. Nama indeks dibagikan di seluruh database Anda. Pastikan setiap nama indeks unik untuk setiap tabel dalam database Anda.

  • TABLE: tabel untuk menambahkan indeks ke.

  • EMBEDDING_COLUMN: kolom yang menyimpan data vector.

  • DISTANCE_FUNCTION: fungsi jarak yang akan digunakan dengan indeks ini. Pilih salah satu opsi berikut:

    • Jarak L2: l2

    • Perkalian titik: dot_product

    • Jarak kosinus: cosine

Perintah ini membuat indeks ScaNN yang dioptimalkan untuk performa penelusuran dan melakukan pemeliharaan indeks otomatis. Jika Anda ingin mengubah salah satu setelan ini, jalankan perintah berikut:

CREATE INDEX INDEX_NAME ON TABLE
       USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
WITH (MODE='AUTO',
      OPTIMIZATION='OPTIMIZATION',
      auto_maintenance='AUTO_MAINTENANCE')

Ganti kode berikut:

  • INDEX_NAME: nama indeks yang ingin Anda buat. Contoh, my_scann_index. Nama indeks dibagikan di seluruh database Anda. Pastikan setiap nama indeks unik untuk setiap tabel dalam database Anda.

  • TABLE: tabel untuk menambahkan indeks ke.

  • EMBEDDING_COLUMN: kolom yang menyimpan data vector.

  • DISTANCE_FUNCTION: fungsi jarak yang akan digunakan dengan indeks ini. Pilih salah satu opsi berikut:

    • Jarak L2: l2

    • Perkalian titik: dot_product

    • Jarak kosinus: cosine

  • (Opsional) OPTIMIZATION: tetapkan ke salah satu opsi berikut:

    • (Default) SEARCH_OPTIMIZED: mengoptimalkan perolehan penelusuran vektor dan latensi penelusuran vektor dengan mengorbankan waktu pembuatan indeks yang lebih lama.

    • BALANCED: menyeimbangkan waktu pembuatan indeks dan performa penelusuran.

    Jika OPTIMIZATION disetel, MODE='AUTO' juga harus disertakan.

  • (Opsional) AUTO_MAINTENANCE: mengontrol apakah pemeliharaan indeks otomatis diaktifkan atau dinonaktifkan. Untuk mengetahui informasi selengkapnya tentang pemeliharaan otomatis, lihat Memelihara indeks vektor.

    • (Default) ON: AlloyDB melakukan pemeliharaan otomatis pada indeks.

    • OFF: AlloyDB tidak melakukan pemeliharaan otomatis pada indeks.

Membuat indeks yang disesuaikan secara manual

Jika aplikasi Anda memiliki persyaratan khusus untuk waktu pembuatan indeks dan recall, Anda dapat membuat dan menyesuaikan indeks ScaNN secara manual.

Untuk membuat indeks ScaNN secara manual untuk kolom yang berisi embedding vektor tersimpan, lihat perintah berikut.

Indeks hierarki dua tingkat

CREATE INDEX INDEX_NAME ON TABLE
       USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
WITH (mode='MANUAL',
      num_leaves=NUM_LEAVES_VALUE,
      quantizer=QUANTIZER,
      auto_maintenance=AUTO_MAINTENANCE);
  • INDEX_NAME: nama indeks yang ingin Anda buat. Misalnya, my_scann_index. Nama indeks dibagikan di seluruh database Anda. Pastikan setiap nama indeks unik untuk setiap tabel dalam database Anda.
  • TABLE: tabel untuk menambahkan indeks.
  • EMBEDDING_COLUMN: kolom yang menyimpan data `vektor`.
  • DISTANCE_FUNCTION: fungsi jarak yang akan digunakan dengan indeks ini. Pilih salah satu opsi berikut:
    • Jarak L2: l2
    • Perkalian titik: dot_product
    • Jarak kosinus: cosine
  • NUM_LEAVES_VALUE: jumlah partisi yang akan diterapkan ke indeks ini. Tetapkan ke nilai apa pun antara 1 dan 30 juta. Untuk mengetahui informasi selengkapnya tentang cara memilih nilai ini, lihat Menyesuaikan indeks ScaNN.
  • QUANTIZER: jenis penguantisasi yang akan digunakan. Perhatikan bahwa indeks ScaNN dapat dimuat ke dalam mesin berbasis kolom untuk lebih mempercepat penelusuran vektor. Pilih salah satu opsi berikut:
    • (Default) SQ8: memberikan keseimbangan performa kueri dengan kehilangan recall minimal. Biasanya kurang dari 1-2%.
    • Pratinjau AH: Hashing asimetris (AH) dikompresi hingga 4x lipat jika dibandingkan dengan SQ8. Untuk performa kueri yang berpotensi lebih baik saat columnar engine diaktifkan dan data indeks serta tabel diisi ke columnar engine, pertimbangkan hal ini untuk performa kueri yang berpotensi lebih baik. Untuk mengetahui informasi selengkapnya, lihat Praktik terbaik untuk menyesuaikan ScaNN.
    • FLAT: memberikan perolehan tertinggi, 99% atau lebih tinggi, dengan mengorbankan performa penelusuran.
  • (Opsional) AUTO_MAINTENANCE: mengontrol apakah pemeliharaan otomatis pada indeks diaktifkan atau dinonaktifkan. Untuk mengetahui informasi selengkapnya tentang pemeliharaan otomatis, lihat Memelihara indeks vektor.
    • (Default) ON: AlloyDB melakukan pemeliharaan otomatis pada indeks.
    • OFF: AlloyDB tidak melakukan pemeliharaan otomatis pada indeks.

Indeks hierarki tiga tingkat

CREATE INDEX INDEX_NAME ON TABLE
       USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
WITH (mode='MANUAL',
      num_leaves=NUM_LEAVES_VALUE,
      quantizer=QUANTIZER,
      auto_maintenance=AUTO_MAINTENANCE,
      max_num_levels = 2);
  • INDEX_NAME: nama indeks yang ingin Anda buat. Misalnya, my_scann_index. Nama indeks dibagikan di seluruh database Anda. Pastikan setiap nama indeks unik untuk setiap tabel dalam database Anda.
  • TABLE: tabel untuk menambahkan indeks.
  • EMBEDDING_COLUMN: kolom yang menyimpan data `vektor`.
  • DISTANCE_FUNCTION: fungsi jarak yang akan digunakan dengan indeks ini. Pilih salah satu opsi berikut:
    • Jarak L2: l2
    • Perkalian titik: dot_product
    • Jarak kosinus: cosine
  • NUM_LEAVES_VALUE: jumlah partisi yang akan diterapkan ke indeks ini. Tetapkan ke nilai apa pun antara 1 dan 30 juta. Untuk mengetahui informasi selengkapnya tentang cara memilih nilai ini, lihat Menyesuaikan indeks ScaNN.
  • QUANTIZER: jenis penguantisasi yang akan digunakan. Perhatikan bahwa indeks ScaNN dapat dimuat ke dalam mesin berbasis kolom untuk lebih mempercepat penelusuran vektor. Pilih salah satu opsi berikut:
    • (Default) SQ8: memberikan keseimbangan performa kueri dengan kehilangan recall minimal. Biasanya kurang dari 1-2%.
    • Pratinjau AH: Hashing asimetris (AH) dikompresi hingga 4x lipat jika dibandingkan dengan SQ8. Untuk performa kueri yang berpotensi lebih baik saat columnar engine diaktifkan dan data indeks serta tabel diisi ke columnar engine, pertimbangkan hal ini untuk performa kueri yang berpotensi lebih baik. Untuk mengetahui informasi selengkapnya, lihat Praktik terbaik untuk menyesuaikan ScaNN.
    • FLAT: memberikan perolehan tertinggi, 99% atau lebih tinggi, dengan mengorbankan performa penelusuran.
  • (Opsional) AUTO_MAINTENANCE: mengontrol apakah pemeliharaan otomatis pada indeks diaktifkan atau dinonaktifkan. Untuk mengetahui informasi selengkapnya tentang pemeliharaan otomatis, lihat Memelihara indeks vektor.
    • (Default) ON: AlloyDB melakukan pemeliharaan otomatis pada indeks.
    • OFF: AlloyDB tidak melakukan pemeliharaan otomatis pada indeks.

Indeks hierarki empat tingkat

Indeks hierarki empat tingkat tersedia dalam Pratinjau.

CREATE INDEX INDEX_NAME ON TABLE
       USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
WITH (mode='MANUAL',
      num_leaves=NUM_LEAVES_VALUE,
      quantizer=QUANTIZER,
      max_num_levels = 3);
  • INDEX_NAME: nama indeks yang ingin Anda buat. Misalnya, my_scann_index. Nama indeks dibagikan di seluruh database Anda. Pastikan setiap nama indeks unik untuk setiap tabel dalam database Anda.
  • TABLE: tabel untuk menambahkan indeks.
  • EMBEDDING_COLUMN: kolom yang menyimpan data `vektor`.
  • DISTANCE_FUNCTION: fungsi jarak yang akan digunakan dengan indeks ini. Pilih salah satu opsi berikut:
    • Jarak L2: l2
    • Perkalian titik: dot_product
    • Jarak kosinus: cosine
  • NUM_LEAVES_VALUE: jumlah partisi yang akan diterapkan ke indeks ini. Tetapkan ke nilai apa pun antara 1 dan 30 juta. Untuk mengetahui informasi selengkapnya tentang cara memilih nilai ini, lihat Menyesuaikan indeks ScaNN.
  • QUANTIZER: jenis penguantisasi yang akan digunakan. Perhatikan bahwa indeks ScaNN dapat dimuat ke dalam mesin berbasis kolom untuk lebih mempercepat penelusuran vektor. Pilih salah satu opsi berikut:
    • (Default) SQ8: memberikan keseimbangan performa kueri dengan kehilangan recall minimal. Biasanya kurang dari 1-2%.
    • Pratinjau AH: Hashing asimetris (AH) dikompresi hingga 4x lipat jika dibandingkan dengan SQ8. Untuk performa kueri yang berpotensi lebih baik saat columnar engine diaktifkan dan data indeks serta tabel diisi ke columnar engine, pertimbangkan hal ini untuk performa kueri yang berpotensi lebih baik. Untuk mengetahui informasi selengkapnya, lihat Praktik terbaik untuk menyesuaikan ScaNN.
    • FLAT: memberikan perolehan tertinggi, 99% atau lebih tinggi, dengan mengorbankan performa penelusuran.

Mengonversi indeks yang disesuaikan secara manual menjadi indeks yang disesuaikan secara otomatis

Untuk mengonversi indeks yang disesuaikan secara manual menjadi indeks yang disesuaikan secara otomatis, selesaikan langkah-langkah berikut:

  1. Mereset semua parameter kueri yang ditentukan untuk indeks yang disesuaikan secara manual.

    ALTER INDEX INDEX_NAME RESET (PARAMETER_NAME);
    

    Ganti variabel berikut:

    • INDEX_NAME: nama indeks yang ingin Anda konversi. Contoh, my_scann_index. Nama indeks digunakan bersama di seluruh database Anda. Pastikan setiap nama indeks unik untuk setiap tabel di database Anda.

    • PARAMETER_NAME: daftar yang dipisahkan koma yang berisi nama parameter kueri yang ingin Anda reset. Contoh, num_leaves, quantization.

      Perhatikan bahwa Anda harus mereset semua parameter kueri lainnya sebelum mereset num_leaves.

  2. Mengindeks ulang indeks yang disesuaikan secara manual untuk mengonversinya menjadi indeks yang disesuaikan secara otomatis.

    REINDEX INDEX CONCURRENTLY INDEX_NAME;
    

Membuat indeks ScaNN untuk jenis data real[]

Untuk membuat indeks untuk kolom penyematan yang menggunakan jenis data real[] alih-alih vector, transmisikan kolom ke jenis data vector:

CREATE INDEX INDEX_NAME ON TABLE
USING scann (CAST(EMBEDDING_COLUMN AS vector(DIMENSIONS)) DISTANCE_FUNCTION)

Ganti kode berikut:

  • INDEX_NAME: nama indeks yang ingin Anda buat. Contoh, my_scann_index. Nama indeks dibagikan di seluruh database Anda. Pastikan setiap nama indeks unik untuk setiap tabel dalam database Anda.

  • TABLE: tabel untuk menambahkan indeks ke.

  • DIMENSIONS: jumlah dimensi yang didukung model.

  • EMBEDDING_COLUMN: kolom yang menyimpan data vector.

  • DISTANCE_FUNCTION: fungsi jarak yang akan digunakan dengan indeks ini. Pilih salah satu opsi berikut:

    • Jarak L2: l2

    • Perkalian titik: dot_product

    • Jarak kosinus: cosine

Melihat progres pengindeksan

Untuk melihat progres pengindeksan, gunakan tampilan pg_stat_progress_create_index:

SELECT * FROM pg_stat_progress_create_index;

Kolom phase menampilkan status pembuatan indeks Anda saat ini. Setelah fase pembuatan indeks selesai, baris untuk indeks tidak terlihat.

Membuat indeks yang ditangguhkan untuk tabel kosong atau tabel dengan baris yang tidak mencukupi

Secara default, Anda tidak dapat membuat indeks ScaNN pada tabel yang kosong atau memiliki lebih sedikit baris daripada nilai opsi indeks num_leaves.

Untuk melewati batasan ini, aktifkan pembuatan indeks yang ditangguhkan agar AlloyDB menangguhkan pembuatan indeks hingga jumlah baris dalam tabel mencapai nilai minimum yang ditentukan num_leaves. Setelah memenuhi nilai minimum, AlloyDB akan memulai pembuatan indeks di latar belakang.

Operasi yang ditangguhkan ini adalah proses non-blocking, sehingga operasi database lainnya seperti pembacaan dan penulisan dapat berlanjut tanpa gangguan. Karena pembangunan ulang indeks terjadi di latar belakang, pembuatan indeks yang ditangguhkan cocok saat tabel menyerap baris data dalam batch kecil. Penyusunan ulang indeks dipicu secara otomatis setelah jumlah baris mencapai nilai minimum.

Namun, jika Anda berencana menyisipkan sejumlah besar baris ke dalam tabel dalam satu transaksi, sebaiknya pisahkan transaksi menjadi beberapa transaksi atau buat indeks ScaNN tanpa mengaktifkan pembuatan indeks yang ditangguhkan.

Mengaktifkan pembuatan indeks yang ditangguhkan

Untuk mengaktifkan pembuatan indeks yang ditangguhkan, ikuti langkah-langkah berikut:

  1. Aktifkan flag scann.enable_index_maintenance (diaktifkan secara default) dan flag scann.enable_preview_features. Flag scann.enable_preview_features juga mengaktifkan fitur pratinjau lainnya.

    gcloud alloydb instances update INSTANCE_ID \
       --database-flags scann.enable_index_maintenance=on \
       --database-flags scann.enable_preview_features=on \
       --region=REGION_ID \
       --cluster=CLUSTER_ID \
       --project=PROJECT_ID
    

    Ganti kode berikut:

    • INSTANCE_ID: ID instance.
    • REGION_ID: Region tempat instance ditempatkan—misalnya, us-central1.
    • CLUSTER_ID: ID cluster tempat instance ditempatkan.
    • PROJECT_ID: ID project tempat cluster ditempatkan.
  2. Buat indeks ScaNN. Jika Anda membuat indeks dalam mode manual, pastikan parameter auto_maintenance disetel ke on. Untuk mengetahui informasi selengkapnya, lihat Membuat indeks yang disesuaikan secara manual.

Batasan

  • Proses latar belakang pembuatan indeks otomatis menggunakan nilai flag tingkat database. Meskipun Anda menetapkan flag tingkat sesi menggunakan perintah SET LOCAL, proses akan mempertimbangkan nilai flag yang ditetapkan di tingkat database.
  • Jika Anda berencana memasukkan data dalam jumlah besar secara massal ke dalam tabel kosong dalam satu transaksi, sebaiknya jalankan transaksi penyisipan tunggal, lalu buat indeks ScaNN.

Memaksa pembuatan indeks pada tabel kosong atau kecil

AlloyDB menggunakan validasi untuk mencegah pembuatan indeks ScaNN pada tabel kosong atau tabel dengan sangat sedikit baris karena alasan berikut:

  • Indeks ScaNN dilatih dengan data yang tidak mencukupi. Hal ini dapat menyebabkan perolehan yang buruk untuk penelusuran kesamaan vektor.

  • Performa penulisan ke database mungkin menurun.

Sebaiknya tunda pembuatan indeks jika performa tidak optimal.

Namun, dalam beberapa skenario pengembangan atau pengujian, Anda mungkin perlu membuat indeks pada tabel kosong atau kecil. Dalam kasus ini, Anda dapat menerapkan pembuatan indeks. Perhatikan bahwa pembuatan indeks paksa memerlukan hak istimewa SUPERUSER.

Untuk memaksakan pembuatan indeks, selesaikan langkah-langkah berikut:

  1. Tetapkan parameter tingkat sesi scann.allow_blocked_operations creation ke true di database:

    SET scann.allow_blocked_operations = true;
    
  2. Jika pengguna yang Anda gunakan untuk menjalankan kueri ini tidak memiliki hak istimewa SUPERUSER, tetapkan hak istimewa tersebut:

    CREATE USER USERNAME WITH SUPERUSER PASSWORD PASSWORD;
    

    Ganti variabel berikut:

    • USERNAME: nama pengguna yang ingin Anda beri hak istimewa SUPERUSER.
    • PASSWORD: sandi pengguna.

Membangun indeks secara paralel

Untuk membuat indeks Anda lebih cepat, AlloyDB mungkin otomatis membuat beberapa pekerja paralel, bergantung pada set data dan jenis indeks yang Anda pilih. Error ini sering kali dipicu saat membuat indeks ScaNN tiga atau empat tingkat atau jika set data Anda melebihi 100 juta baris.

Meskipun AlloyDB mengoptimalkan jumlah pekerja paralel secara otomatis, Anda dapat menyesuaikan pekerja paralel menggunakan parameter perencanaan kueri PostgreSQL berikut:

Untuk menghindari masalah kehabisan memori saat Anda membuat indeks ScaNN, pastikan flag database maintenance_work_mem dan shared_buffers ditetapkan ke nilai yang lebih kecil dari total memori mesin.

Menjalankan kueri

Setelah menyimpan dan mengindeks embedding di database, Anda dapat mulai mengirimkan kueri data. Anda tidak dapat menjalankan kueri penelusuran massal menggunakan ekstensi alloydb_scann.

Untuk menemukan tetangga semantik terdekat untuk string teks, Anda dapat menggunakan fungsi google_ml.embedding() untuk menerjemahkan teks menjadi vektor.

Karena google_ml.embedding() menampilkan array sebenarnya, Anda harus melakukan transmisi eksplisit panggilan fungsi ke vector sebelum menerapkannya ke salah satu operator tetangga terdekat, misalnya, <-> untuk jarak L2. Operator ini kemudian dapat menggunakan indeks ScaNN untuk menemukan baris database dengan embedding yang paling mirip secara semantik.

SELECT * FROM TABLE
ORDER BY EMBEDDING_COLUMN DISTANCE_FUNCTION_QUERY
  google_ml.embedding(
      model_id => 'MODEL_ID',
      content => 'CONTENT')::vector
LIMIT ROW_COUNT

Ganti variabel berikut:

  • TABLE: tabel yang berisi embedding untuk membandingkan teks.

  • EMBEDDING_COLUMN: kolom yang berisi embedding tersimpan.

  • DISTANCE_FUNCTION_QUERY: fungsi jarak yang akan digunakan dengan kueri ini. Pilih kueri yang setara untuk fungsi jarak saat Anda membuat indeks:

    • Jarak L2: <->

    • Produk dalam: <#>

    • Jarak kosinus: <=>

  • MODEL_ID: ID model embedding terdaftar yang ingin Anda gunakan.

  • CONTENT: string teks yang ingin Anda terjemahkan menjadi embedding dan cari.

  • ROW_COUNT: jumlah baris yang akan ditampilkan. Misalnya, tentukan 1 jika Anda menginginkan satu kecocokan terbaik.

Langkah berikutnya