Indeks penelusuran

Halaman ini menjelaskan cara menambahkan indeks penelusuran ke tabel. Indeks pencarian diperlukan untuk membuat struktur tabel yang yang diperlukan untuk mengizinkan penelusuran teks lengkap di Spanner.

Indeks penelusuran teks lengkap

Anda dapat membuat indeks penelusuran di kolom mana pun yang ingin dibuat tersedia untuk penelusuran teks lengkap. Untuk membuat indeks penelusuran, gunakan CREATE SEARCH INDEX Pernyataan DDL, atau perbarui pernyataan tersebut menggunakan Pernyataan DDL ALTER SEARCH INDEX. Spanner secara otomatis menyusun dan memelihara indeks pencarian, termasuk menambah dan memperbarui data dalam indeks penelusuran segera setelah data tersebut berubah dalam database.

Indeks penelusuran dapat dipartisi atau tidak dipartisi, bergantung pada jenisnya kueri yang ingin Anda percepat.

  • Contoh saat indeks yang dipartisi adalah pilihan terbaik adalah ketika aplikasi mengirimkan kueri ke kotak surat email. Setiap kueri dibatasi ke kueri kotak surat.

  • Contoh saat kueri yang tidak dipartisi adalah pilihan terbaik adalah ada kueri di semua kategori produk dalam katalog produk.

Selain penelusuran teks lengkap, indeks penelusuran Spanner mendukung berikut ini:

  • {i>Substring search<i}, yang merupakan jenis kueri untuk mencari {i>string<i} (substring) di dalam isi teks yang lebih besar.
  • Akselerasi untuk kueri yang memiliki ekspresi pencocokan numerik dan persis.
  • Menggabungkan kondisi pada subset data yang diindeks ke dalam satu pemindaian indeks.

Sementara indeks pencarian mendukung penggunaan data non-tekstual, seperti angka dan string pencocokan persis, kasus penggunaan yang paling umum untuk indeks penelusuran adalah mengindeks teks dalam dokumen.

Untuk menunjukkan kemampuan indeks pencarian, anggaplah ada sebuah tabel yang menyimpan informasi tentang album musik:

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  AlbumTitle STRING(MAX)
) PRIMARY KEY(AlbumId);

Spanner memiliki beberapa fungsi token yang membuat token kata. Untuk mengubah tabel sebelumnya agar pengguna dapat menjalankan penelusuran teks lengkap untuk menemukan judul album, gunakan fungsi TOKENIZE_FULLTEXT untuk membuat token dari judul album. Lalu, buat kolom yang menggunakan jenis data TOKENLIST untuk menyimpan output tokenisasi dari TOKENIZE_FULLTEXT. Untuk contoh ini, kita membuat kolom AlbumTitle_Tokens.

ALTER TABLE Albums
  ADD COLUMN AlbumTitle_Tokens TOKENLIST
  AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN;

Berikut ini menggunakan DDL CREATE SEARCH INDEX untuk membuat indeks penelusuran (AlbumsIndex) pada token AlbumTitle (AlbumTitle_Tokens):

CREATE SEARCH INDEX AlbumsIndex
  ON Albums(AlbumTitle_Tokens);

Setelah menambahkan indeks penelusuran, gunakan kueri SQL untuk menemukan album yang cocok kriteria pencarian. Contoh:

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")

Konsistensi data

Saat indeks dibuat, Spanner menggunakan proses otomatis untuk mengisi ulang data untuk memastikan konsistensi. Saat operasi tulis di-commit, indeks diperbarui dalam transaksi yang sama. Spanner secara otomatis melakukan pemeriksaan konsistensi data.

Definisi skema indeks penelusuran

Indeks penelusuran ditentukan pada satu atau beberapa kolom TOKENLIST pada tabel. Telusuri indeks memiliki komponen berikut:

  • Tabel dasar: Tabel Spanner yang memerlukan pengindeksan.
  • Kolom TOKENLIST: Kumpulan kolom yang menentukan token yang memerlukan pengindeksan. Urutan kolom ini tidak penting.

Misalnya, dalam pernyataan berikut, tabel dasarnya adalah Album. TOKENLIST kolom dibuat di AlbumTitle (AlbumTitle_Tokens) dan Rating (Rating_Tokens).

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  SingerId INT64 NOT NULL,
  ReleaseTimestamp INT64 NOT NULL,
  AlbumTitle STRING(MAX),
  Rating FLOAT64,
  AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN,
  Rating_Tokens TOKENLIST AS (TOKENIZE_NUMBER(Rating)) HIDDEN
) PRIMARY KEY(AlbumId);

Gunakan pernyataan CREATE SEARCH INDEX berikut untuk membuat indeks penelusuran menggunakan token untuk AlbumTitle dan Rating:

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Tokens, Rating_Tokens)
PARTITION BY SingerId
ORDER BY ReleaseTimestamp DESC

Indeks penelusuran memiliki opsi berikut:

  • Partisi: Grup kolom opsional yang membagi indeks penelusuran. Membuat kueri indeks yang dipartisi sering kali jauh lebih efisien dibandingkan membuat kueri indeks yang tidak dipartisi. Untuk informasi selengkapnya, lihat Indeks penelusuran partisi.
  • Kolom tata urutan: Kolom INT64 opsional yang menetapkan urutan pengambilan dari indeks penelusuran. Untuk selengkapnya informasi, lihat Telusuri tata urutan indeks.
  • Interleaving: Seperti indeks sekunder, Anda dapat menyisipkan indeks penelusuran. Indeks penelusuran berselisih menggunakan lebih sedikit resource untuk menulis dan menggabungkan pada tabel dasar. Untuk informasi selengkapnya, lihat Penelusuran sisipan indeks.
  • Klausa opsi: Daftar pasangan nilai kunci yang menggantikan nilai default pengaturan indeks pencarian.

Untuk informasi selengkapnya, lihat referensi CREATE SEARCH INDEX.

Tata letak internal indeks penelusuran

Elemen penting dari representasi internal indeks pencarian adalah docid, yang berfungsi sebagai representasi kunci utama yang hemat penyimpanan dari tabel dasar yang bisa panjangnya sembarangan. Hal itu juga yang menciptakan urutan tata letak data internal sesuai dengan ORDER BY yang diberikan pengguna kolom Klausa CREATE SEARCH INDEX. ASCII direpresentasikan sebagai satu atau dua bilangan bulat 64-bit.

Indeks penelusuran diimplementasikan secara internal sebagai pemetaan dua tingkat:

  1. Token ke docid
  2. Docid ke kunci utama tabel dasar

Skema ini menghasilkan penghematan penyimpanan yang signifikan dengan Spanner tidak perlu menyimpan kunci utama tabel basis lengkap untuk setiap <token, document> pasangan.

Ada dua jenis indeks fisik yang mengimplementasikan dua level pemetaan:

  1. Indeks sekunder yang memetakan kunci partisi dan asam ke tabel dasar {i>primary key<i}-nya. Pada contoh di bagian sebelumnya, hal ini memetakan {SingerId, ReleaseTimestamp, uid} ke {SingerId, AlbumId}. Indeks sekunder juga menyimpan semua kolom yang ditentukan dalam klausa STORING dari CREATE SEARCH INDEX.
  2. Indeks token memetakan token ke docid, serupa dengan indeks terbalik pada literatur untuk pengambilan informasi. Spanner mempertahankan indeks token terpisah untuk setiap TOKENLIST dari indeks penelusuran. Secara logis, Indeks token mengelola daftar docid untuk setiap token dalam setiap partisi (dikenal dalam pengambilan informasi sebagai daftar postingan). Daftar ini diurutkan oleh token untuk pengambilan cepat, dan di dalam daftar {i> docid<i} digunakan untuk memesan. Indeks token individual adalah detail implementasi yang tidak diekspos Spanner API.

Spanner mendukung empat opsi berikut untuk docid.

Indeks penelusuran Docid Perilaku
Klausa ORDER BY dihapus untuk indeks penelusuran { uid } Spanner menambahkan nilai unik (UID) tersembunyi untuk mengidentifikasi setiap baris.
ORDER BY column { column, uid } Spanner menambahkan kolom UID sebagai binding di antara baris dengan nilai column yang sama dalam partisi.
ORDER BY column ... OPTIONS (disable_automatic_uid_column=true) { column } Kolom UID tidak ditambahkan. Nilai column harus unik dalam partisi.
ORDER BY column1, column2 ... OPTIONS (disable_automatic_uid_column=true) { column1, column2 } Kolom UID tidak ditambahkan. Kombinasi nilai column1 dan column2 harus unik dalam partisi.

Catatan penggunaan:

  • Kolom UID internal tidak diekspos melalui Spanner Compute Engine API.
  • Dalam indeks yang tidak menambahkan UID, transaksi apa pun akan gagal jika menghasilkan dua baris dengan jumlah yang sama (partisi,tata urutan).

Misalnya, perhatikan data berikut:

AlbumId SingerId ReleaseTimestamp AlbumTitle
a1 1 997 besar
a2 1 743 Kucing besar

Dengan asumsi kolom presort berada dalam urutan menaik, isi token dipartisi oleh SingerId akan mempartisi konten indeks token dalam dengan cara berikut:

SingerId _token ReleaseTimestamp uid
1 besar 743 uid1
1 besar 997 uid2
1 cat 743 uid1
1 dog 997 uid2

Sharding indeks penelusuran

Saat Spanner membagi tabel. mendistribusikan data indeks pencarian sehingga semua token dalam baris tabel dasar tertentu berada di bagian yang sama. Dengan kata lain, indeks penelusuran merupakan hasil sharding dokumen. Strategi sharding ini memiliki implikasi performa yang signifikan:

  1. Jumlah server yang berkomunikasi dengan setiap transaksi tetap konstan, terlepas dari jumlah token atau jumlah TOKENLIST kolom.
  2. Kueri penelusuran yang melibatkan beberapa ekspresi bersyarat dijalankan secara independen pada setiap bagian, sehingga menghindari overhead performa yang terkait dengan gabungan terdistribusi.

Indeks penelusuran memiliki dua mode distribusi:

  • Sharding seragam (default). Dalam sharding seragam, data terindeks untuk setiap baris tabel dasar ditetapkan secara acak ke bagian indeks dari partisi.
  • Sharding urutan penyortiran. Dalam sharding tata urutan, data untuk setiap baris tabel dasar ditetapkan ke bagian indeks partisi berdasarkan ORDER BY seperti baris dan kolom. Misalnya, dalam kasus tata urutan menurun, semua baris dengan nilai urutan tertinggi muncul di bagian indeks pertama partisi, dan grup nilai tata urutan tertinggi berikutnya di pemisahan berikutnya.

Mode sharding ini memiliki imbal balik antara risiko hotspotting dan biaya kueri:

  • Indeks penelusuran dengan sharding tata urutan rentan terhadap hotspotting ketika indeks diurutkan berdasarkan stempel waktu. Untuk informasi selengkapnya, lihat Memilih kunci utama untuk mencegah hotspot. Di sisi lain, ketika beban tulis meningkat pada berbagai dokumen, sharding yang seragam memastikan bahwa peningkatan didistribusikan secara merata sharding.
  • Pemisahan berbasis beban standar membuat pemisahan tambahan yang menyediakan perlindungan yang memadai terhadap hotspotting. Kelemahan dari sharding seragam bahwa ia dapat menggunakan lebih banyak sumber daya untuk beberapa jenis kueri.

Mode sharding indeks penelusuran dikonfigurasi menggunakan klausa OPTIONS:

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Tokens, Rating_Tokens)
PARTITION BY SingerId
ORDER BY ReleaseTimestamp DESC
OPTIONS (sort_order_sharding = true);

Jika sort_order_sharding=false ditetapkan atau tidak ditentukan, indeks penelusuran akan yang dibuat menggunakan sharding seragam.

Indeks penelusuran berselisih

Seperti indeks sekunder, Anda dapat menyisipkan indeks penelusuran di tabel induk dari tabel dasar. Alasan utama untuk menggunakan penelusuran sisipan indeks adalah untuk menempatkan data tabel dasar dengan data indeks untuk partisi kecil. Kolokasi oportunistik ini memiliki keuntungan sebagai berikut:

  • Penulisan tidak perlu melakukan commit dua fase.
  • Sambungan belakang indeks penelusuran dengan tabel dasar tidak didistribusikan.

Indeks penelusuran berselisih memiliki batasan berikut:

  1. Hanya di-sharding urutan penyortiran indeks dapat disisipi.
  2. Indeks penelusuran hanya dapat disisipi di tabel tingkat teratas (bukan di turunan tabel).
  3. Seperti tabel sisipan dan indeks sekunder, buatlah kunci dari tabel induk sebagai awalan dari kolom PARTITION BY di sisipan indeks penelusuran.

Contoh berikut menunjukkan cara menentukan indeks penelusuran sisipan:

CREATE TABLE Singers (
  SingerId INT64 NOT NULL
) PRIMARY KEY(SingerId);

CREATE TABLE Albums (
  SingerId INT64 NOT NULL,
  AlbumId STRING(MAX) NOT NULL,
  AlbumTitle STRING(MAX),
  AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN
) PRIMARY KEY(SingerId, AlbumId),
  INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Tokens)
PARTITION BY SingerId
INTERLEAVE IN Singers
OPTIONS (sort_order_sharding = true);

Indeks penelusuran yang difilter dengan NULL

Indeks penelusuran dapat menggunakan sintaksis WHERE column IS NOT NULL untuk mengecualikan baris tabel dasar. Pemfilteran NULL bisa berlaku untuk kunci partisi, kolom pesanan, dan kolom yang disimpan. Pemfilteran NULL pada kolom array yang disimpan tidak diizinkan.

Contoh

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Tokens)
STORING Genre
WHERE Genre IS NOT NULL

Kueri harus menentukan kondisi pemfilteran NULL (Genre IS NOT NULL untuk contoh ini) dalam klausa WHERE. Jika tidak, Pengoptimal Kueri tidak dapat menggunakan indeks pencarian. Untuk informasi selengkapnya, lihat Persyaratan kueri SQL.

Gunakan pemfilteran NULL pada kolom yang dihasilkan untuk mengecualikan baris berdasarkan kriteria arbitrer. Untuk informasi selengkapnya, lihat Membuat indeks parsial menggunakan kolom yang dibuat.

Langkah selanjutnya