Menemukan perkiraan tetangga terdekat untuk mengindeks dan membuat kueri embedding vektor di Spanner

Halaman ini menjelaskan cara membuat indeks vektor dan embedding vektor kueri dengan menggunakan perkiraan jarak kosinus, perkiraan jarak Euclidean, dan fungsi perkiraan titik vektor. Anda dapat menggunakan fungsi untuk menemukan perkiraan tetangga terdekat (ANN) di Spanner. Jika set data berukuran kecil, Anda dapat menggunakan K-nearest nearby (KNN) untuk menemukan vektor k-terdekat yang tepat. Namun, seiring dengan bertambahnya set data Anda, latensinya dan biaya pencarian KNN juga meningkat. Anda dapat menggunakan ANN untuk menemukan perkiraan k-nearest tetangga dengan latensi dan biaya yang berkurang secara signifikan.

Perkiraan k-tetangga terdekat

Dalam penelusuran ANN, vektor yang ditampilkan k bukanlah top k-nearest sebenarnya tetangga. Terkadang, beberapa vektor yang tidak termasuk dalam top k-nearest tetangga akan ditampilkan. Hal ini dikenal sebagai hilangnya recall. Berapa banyak penurunan penarikan dapat diterima tergantung pada kasus penggunaannya, tetapi dalam kebanyakan kasus, kehilangan untuk meningkatkan performa database adalah kompromi.

Untuk detail selengkapnya tentang fungsi perkiraan jarak Spanner, lihat:

Indeks vektor

Spanner mempercepat penelusuran vektor ANN dengan menggunakan indeks vektor. Indeks ini memanfaatkan layanan Scalable Nearest milik Google Research Tetangga (ScaNN), algoritma tetangga terdekat yang sangat efisien.

Indeks vektor menggunakan struktur berbasis pohon untuk mempartisi data dan memfasilitasi penelusuran menjadi lebih cepat. Spanner menawarkan dua level dan tiga level konfigurasi hierarkinya:

  • Konfigurasi pohon dua tingkat: Node daun (num_leaves) berisi kelompok vektor yang terkait erat bersama dengan sentroidnya yang sesuai. Akar terdiri dari sentroid dari semua node daun.
  • Konfigurasi pohon tiga tingkat: Mirip secara konsep dengan pohon dua tingkat, meskipun memperkenalkan lapisan cabang tambahan (num_branches), tempat node daun sentroid dipartisi lebih lanjut untuk membentuk tingkat root (num_leaves).

Selain itu, Anda harus membangun indeks vektor dengan metrik jarak tertentu. Anda dapat memilih metrik jarak yang paling sesuai untuk kasus penggunaan Anda dengan distance_type ke salah satu dari COSINE, DOT_PRODUCT, atau EUCLIDEAN.

Untuk informasi selengkapnya, lihat pernyataan VECTOR INDEX.

Batasan

Indeks vektor Spanner memiliki batasan berikut:

  • ALTER VECTOR INDEX tidak didukung.

Membuat indeks vektor

Untuk mengoptimalkan indeks vektor dengan perolehan dan performa yang baik, kami sarankan Anda membuat indeks vektor setelah sebagian besar baris dengan embedding yang ditulis ke {i>database<i} Anda. Anda mungkin juga perlu secara berkala membangun ulang indeks vektor setelah Anda menyisipkan data baru. Untuk informasi selengkapnya, lihat Membuat ulang indeks vektor.

Untuk membuat indeks vektor dengan pohon dua tingkat dan 1000 simpul daun pada Tabel Documents dengan kolom penyematan DocEmbedding menggunakan kosinus jarak:

CREATE VECTOR INDEX DocEmbeddingIndex
  ON Documents(DocEmbedding)
  OPTIONS (distance_type = 'COSINE', tree_depth = 2, num_leaves = 1000);

Untuk membuat indeks vektor dengan pohon tiga tingkat dan 1000000 node daun:

CREATE VECTOR INDEX DocEmbeddingIndex
  ON Documents(NullableDocEmbedding)
  WHERE NullableDocEmbedding IS NOT NULL
  OPTIONS (distance_type = 'COSINE', tree_depth = 3, num_branches=1000, num_leaves = 1000000);

Jika kolom penyematan nullable, Anda harus mendeklarasikannya dengan Klausa WHERE column_name IS NOT NULL:

CREATE VECTOR INDEX DocEmbeddingIndex
  ON Documents(NullableDocEmbedding)
  WHERE NullableDocEmbedding IS NOT NULL
  OPTIONS (distance_type = 'COSINE', tree_depth = 2, num_leaves = 1000);

Embedding vektor kueri

Untuk membuat kueri indeks vektor, gunakan salah satu dari tiga fungsi perkiraan jarak:

  • APPROX_COSINE_DISTANCE
  • APPROX_EUCLIDEAN_DISTANCE
  • APPROX_DOT_PRODUCT

Batasan saat menggunakan fungsi perkiraan jarak mencakup berikut ini:

  • Anda harus memberikan petunjuk kueri untuk menggunakan indeks vektor.
  • Anda harus menggunakan ekspresi konstan sebagai satu argumen fungsi jarak (misalnya, parameter atau literal).
  • Kueri atau sub kueri yang menggunakan fungsi perkiraan jarak harus ambil bentuk tertentu: fungsi jarak harus menjadi satu-satunya tombol ORDER BY, dan batas harus ditentukan.

Untuk daftar batasan terperinci, lihat halaman referensi fungsi perkiraan jarak.

Contoh

Untuk menelusuri 100 vektor terdekat ke [1.0, 2.0, 3.0]:

SELECT DocId
FROM Documents@{FORCE_INDEX=DocEmbeddingIndex}
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
  ARRAY<FLOAT32>[1.0, 2.0, 3.0], DocEmbedding,
  options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100

Jika kolom penyematan nullable:

SELECT DocId
FROM Documents@{FORCE_INDEX=DocEmbeddingIndex}
WHERE NullableDocEmbedding IS NOT NULL
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
  ARRAY<FLOAT32>[1.0, 2.0, 3.0], NullableDocEmbedding,
  options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100

Praktik terbaik

Ikuti praktik terbaik ini untuk mengoptimalkan indeks vektor dan meningkatkan kueri hasil pengujian tersebut.

Menyesuaikan opsi penelusuran vektor

Nilai penelusuran vektor yang paling optimal bergantung pada kasus penggunaan, yakni vektor set data, dan vektor kueri. Anda mungkin perlu melakukan tuning berulang untuk menemukan nilai terbaik untuk beban kerja spesifik Anda.

Berikut adalah beberapa panduan bermanfaat yang harus diikuti saat memilih nilai yang sesuai:

  • tree_depth (tingkat hierarki): Jika tabel yang diindeks memiliki kurang dari 10 juta baris, gunakan tree_depth dari 2. Jika tidak, tree_depth sebesar 3 mendukung tabel hingga sekitar 10 miliar baris.

  • num_leaves: Menggunakan akar kuadrat dari jumlah baris dalam set data. J nilai yang lebih besar dapat meningkatkan waktu build indeks vektor. Hindari menyetel num_leaves lebih besar dari table_row_count/1000 karena ini menyebabkan daun yang terlalu kecil dan performa yang buruk.

  • num_leaves_to_search: Opsi ini menentukan jumlah node daun indeks ditelusuri. Meningkatkan num_leaves_to_search akan meningkatkan ingatan, tetapi juga meningkatkan latensi dan biaya. Sebaiknya gunakan angka yang merupakan 1% dari total jumlah daun yang ditentukan dalam pernyataan CREATE VECTOR INDEX sebagai nilai untuk num_leaves_to_search. Jika Anda menggunakan klausa filter, tingkatkan nilai ini untuk memperluas pencarian.

Jika perolehan yang dapat diterima tercapai, tetapi biaya kueri terlalu tinggi, sehingga QPS maksimum rendah, coba tingkatkan num_leaves dengan mengikuti langkah:

  1. Tetapkan num_leaves ke kelipatan k dari nilai aslinya (misalnya, 2 * sqrt(table_row_count)).
  2. Tetapkan num_leaves_to_search agar sama dengan kelipatan k dari nilai aslinya.
  3. Lakukan eksperimen dengan mengurangi num_leaves_to_search untuk meningkatkan biaya dan QPS sembari mempertahankan ingatan.

Meningkatkan ingatan

Ada beberapa kemungkinan memburuknya ingatan Anda, termasuk yang berikut:

  • num_leaves_to_search terlalu kecil: Mungkin akan lebih sulit untuk menemukan tetangga terdekat untuk beberapa vektor kueri, sehingga num_leaves_to_search untuk menelusuri lebih banyak daun dapat membantu meningkatkan ingatan. Terkini mungkin telah bergeser untuk memuat lebih banyak vektor yang menantang ini.

  • Indeks vektor perlu dibangun ulang: Struktur pohon indeks vektor dioptimalkan untuk set data pada saat pembuatan, dan akan bersifat statis setelahnya. Oleh karena itu, jika vektor yang berbeda secara signifikan ditambahkan setelah membuat indeks vektor awal, maka struktur pohon mungkin kurang optimal, sehingga ingatan yang buruk.

Membuat ulang indeks vektor

Untuk membangun kembali indeks vektor tanpa periode nonaktif:

  1. Membuat indeks vektor baru pada kolom embedding yang sama dengan vektor saat ini indeks, memperbarui parameter (misalnya, OPTIONS) yang sesuai.
  2. Setelah pembuatan indeks selesai, ubah petunjuk FORCE_INDEX mengarah ke indeks baru untuk memperbarui kueri penelusuran vektor. Hal ini memastikan kueri tersebut menggunakan indeks vektor baru. (Anda mungkin juga perlu mengatur ulang num_leaves_to_search dalam kueri baru Anda).
  3. Lepaskan indeks vektor yang usang.

Langkah selanjutnya