Halaman ini menjelaskan cara menambahkan indeks penelusuran. Penelusuran teks lengkap dijalankan terhadap entri di indeks penelusuran.
Cara menggunakan indeks penelusuran
Anda dapat membuat indeks penelusuran pada kolom yang ingin Anda
jadikan tersedia untuk penelusuran teks lengkap. Untuk membuat indeks penelusuran, gunakan pernyataan DDL CREATE SEARCH INDEX
. Untuk memperbarui indeks,
gunakan pernyataan DDL ALTER SEARCH INDEX
. Spanner
otomatis membuat dan mengelola indeks penelusuran, termasuk menambahkan dan
memperbarui data di indeks penelusuran segera setelah data berubah di database.
Partisi indeks penelusuran
Indeks penelusuran dapat dipartisi atau tidak dipartisi, bergantung pada jenis kueri yang ingin Anda percepat.
Contoh saat indeks yang dipartisi adalah pilihan terbaik adalah saat aplikasi membuat kueri kotak surat email. Setiap kueri dibatasi untuk kotak surat tertentu.
Contoh saat kueri yang tidak dipartisi adalah pilihan terbaik adalah saat ada kueri di semua kategori produk dalam katalog produk.
Kasus penggunaan indeks penelusuran
Selain penelusuran teks lengkap, indeks penelusuran Spanner mendukung hal berikut:
- Penelusuran substring, yang merupakan jenis kueri yang mencari string yang lebih pendek (substring) dalam isi teks yang lebih besar.
- Menggabungkan kondisi pada subset data yang diindeks ke dalam satu pemindaian indeks.
Meskipun indeks penelusuran mendukung pengindeksan data non-tekstual, seperti angka dan string pencocokan persis, kasus penggunaan yang paling umum untuk indeks penelusuran adalah mengindeks teks dalam dokumen.
Contoh indeks penelusuran
Untuk menampilkan kemampuan indeks penelusuran, misalkan ada 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 tokenize yang membuat
token. 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. Kemudian, 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;
Contoh berikut 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 dengan kriteria penelusuran. Contoh:
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")
Konsistensi data
Saat indeks dibuat, Spanner menggunakan proses otomatis untuk mengisi ulang data guna memastikan konsistensi. Saat operasi tulis di-commit, indeks akan 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
tabel. Indeks penelusuran memiliki komponen berikut:
- Tabel dasar: tabel Spanner yang memerlukan pengindeksan.
- Kolom
TOKENLIST
: kumpulan kolom yang menentukan token yang perlu pengindeksan. Urutan kolom ini tidak penting.
Misalnya, dalam pernyataan berikut, tabel dasarnya adalah Albums. Kolom TOKENLIST
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 daripada membuat kueri indeks yang tidak dipartisi. Untuk mengetahui informasi selengkapnya, lihat Mempartisi indeks penelusuran.
- Kolom urutan pengurutan: kolom
INT64
opsional yang menetapkan urutan pengambilan dari indeks penelusuran. Untuk informasi selengkapnya, lihat Urutan pengurutan indeks penelusuran. - Interleaving: seperti indeks sekunder, Anda dapat menyisipkan indeks penelusuran. Indeks penelusuran yang diselingi menggunakan lebih sedikit resource untuk menulis dan bergabung dengan tabel dasar. Untuk mengetahui informasi selengkapnya, lihat Indeks penelusuran interleaved.
- Opsi klausa: daftar pasangan nilai kunci yang mengganti setelan default indeks penelusuran.
Untuk informasi selengkapnya, lihat referensi CREATE SEARCH INDEX
.
Tata letak internal indeks penelusuran
Elemen penting dari representasi internal indeks penelusuran adalah
docid, yang berfungsi sebagai representasi penyimpanan yang efisien dari kunci utama
tabel dasar yang dapat panjangnya tidak ditentukan. Ini juga yang membuat
urutan untuk tata letak data internal sesuai dengan kolom ORDER BY
yang disediakan pengguna dari
klausa CREATE SEARCH INDEX
. Nilai ini direpresentasikan sebagai satu atau dua bilangan bulat 64-bit.
Indeks penelusuran diterapkan secara internal sebagai pemetaan dua tingkat:
- Token ke docid
- Docid ke kunci utama tabel dasar
Skema ini menghasilkan penghematan penyimpanan yang signifikan karena Spanner
tidak perlu menyimpan kunci utama tabel dasar lengkap untuk setiap
pasangan <token, document>
.
Ada dua jenis indeks fisik yang menerapkan dua tingkat pemetaan:
- Indeks sekunder yang memetakan kunci partisi dan docid ke kunci utama tabel dasar. Dalam contoh di bagian sebelumnya, tindakan ini memetakan
{SingerId, ReleaseTimestamp, uid}
ke{AlbumId}
. Indeks sekunder juga menyimpan semua kolom yang ditentukan dalam klausaSTORING
dariCREATE SEARCH INDEX
. - Indeks token yang memetakan token ke docid, mirip dengan indeks terbalik dalam
literatur pengambilan informasi. Spanner mempertahankan
indeks token terpisah untuk setiap
TOKENLIST
indeks penelusuran. Secara logis, indeks token mempertahankan daftar docid untuk setiap token dalam setiap partisi (dikenal dalam pengambilan informasi sebagai daftar postingan). Daftar diurutkan oleh token untuk pengambilan yang cepat, dan dalam daftar, docid digunakan untuk pengurutan. Setiap indeks token adalah detail implementasi yang tidak ditampilkan melalui Spanner API.
Spanner mendukung empat opsi berikut untuk docid.
Indeks penelusuran | Docid | Perilaku |
---|---|---|
Klausa ORDER BY dihilangkan untuk indeks penelusuran |
{uid} |
Spanner menambahkan nilai unik (UID) tersembunyi untuk mengidentifikasi setiap baris. |
ORDER BY column |
{column, uid} |
Spanner menambahkan kolom UID sebagai penentu 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 , column2 harus unik dalam partisi. |
Catatan penggunaan:
- Kolom UID internal tidak ditampilkan melalui Spanner API.
- Dalam indeks tempat UID tidak ditambahkan, transaksi yang menambahkan baris dengan yang sudah ada (partisi,urutan pengurutan) akan gagal.
Misalnya, pertimbangkan data berikut:
AlbumId | SingerId | ReleaseTimestamp | SongTitle |
---|---|---|---|
a1 | 1 | 997 | Hari yang indah |
a2 | 1 | 743 | Mata yang indah |
Dengan asumsi kolom prapengurutan dalam urutan menaik, konten indeks token
yang dipartisi oleh SingerId
akan mempartisi konten indeks token dengan
cara berikut:
SingerId | _token | ReleaseTimestamp | uid |
---|---|---|---|
1 | cantik | 743 | uid1 |
1 | cantik | 997 | uid2 |
1 | hari | 743 | uid1 |
1 | mata | 997 | uid2 |
Sharding indeks penelusuran
Saat membagi tabel, Spanner akan mendistribusikan data indeks penelusuran sehingga semua token dalam baris tabel dasar tertentu berada dalam bagian yang sama. Dengan kata lain, indeks penelusuran di-shard dokumen. Strategi sharding ini memiliki implikasi performa yang signifikan:
- Jumlah server yang dikomunikasikan oleh setiap transaksi tetap konstan, terlepas dari jumlah token atau jumlah kolom
TOKENLIST
yang diindeks. - Kueri penelusuran yang melibatkan beberapa ekspresi kondisional dijalankan secara independen pada setiap bagian, sehingga menghindari overhead performa yang terkait dengan join terdistribusi.
Indeks penelusuran memiliki dua mode distribusi:
- Sharding seragam (default). Dalam sharding seragam, data yang diindeks untuk setiap baris tabel dasar ditetapkan secara acak ke bagian indeks partisi.
- Sharding urutan pengurutan. Dalam sharding urutan pengurutan, data untuk setiap baris tabel dasar
diatribusikan ke bagian indeks partisi berdasarkan kolom
ORDER BY
. Misalnya, dalam kasus urutan pengurutan menurun, semua baris dengan nilai urutan pengurutan tertinggi akan muncul pada bagian indeks pertama dari partisi, dan grup nilai urutan pengurutan tertinggi berikutnya pada bagian berikutnya.
Mode sharding ini memiliki kompromi antara risiko hotspotting dan biaya kueri:
- Indeks penelusuran yang di-sharding menurut urutan pengurutan rentan terhadap hotspot saat indeks diurutkan menurut stempel waktu. Untuk informasi selengkapnya, lihat Memilih kunci utama untuk mencegah hotspot. Di sisi lain, saat beban operasi tulis meningkat di berbagai dokumen, sharding seragam memastikan bahwa peningkatan tersebut didistribusikan secara merata di seluruh shard.
- Pemisahan berbasis beban standar membuat pemisahan tambahan yang memberikan perlindungan yang memadai terhadap hotspotting. Kelemahan sharding seragam adalah dapat menggunakan lebih banyak resource 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 dibuat menggunakan sharding seragam.
Indeks penelusuran yang diselang-seling
Seperti indeks sekunder, Anda dapat menyelang-seling indeks penelusuran di tabel induk tabel dasar. Alasan utama menggunakan indeks penelusuran interleaved adalah untuk menempatkan data tabel dasar dengan data indeks untuk partisi kecil. Kolokasi oportunistik ini memiliki keunggulan berikut:
- Operasi tulis tidak perlu melakukan commit dua fase.
- Join balik indeks penelusuran dengan tabel dasar tidak didistribusikan.
Indeks penelusuran yang diselang-seling memiliki batasan berikut:
- Hanya indeks yang di-shard urutan pengurutan yang dapat diselang-seling.
- Indeks penelusuran hanya dapat diselang-seling di tabel tingkat atas (bukan di tabel turunan).
- Seperti tabel yang diselingi dan indeks sekunder, buat kunci
tabel induk menjadi awalan kolom
PARTITION BY
dalam indeks penelusuran yang diselingi.
Menentukan indeks penelusuran yang diselang-seling
Contoh berikut menunjukkan cara menentukan indeks penelusuran yang diselingi:
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);
Urutan pengurutan indeks penelusuran
Persyaratan untuk definisi urutan pengurutan indeks penelusuran berbeda dengan indeks sekunder.
Misalnya, pertimbangkan tabel berikut:
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
ReleaseTimestamp INT64 NOT NULL,
AlbumName STRING(MAX),
AlbumName_Token TOKENLIST AS (TOKEN(AlbumName)) HIDDEN
) PRIMARY KEY(AlbumId);
Aplikasi dapat menentukan indeks sekunder untuk mencari informasi menggunakan
AlbumName
yang diurutkan menurut ReleaseTimestamp
:
CREATE INDEX AlbumsSecondaryIndex ON Albums(AlbumName, ReleaseTimestamp DESC);
Indeks penelusuran yang setara terlihat seperti berikut (ini menggunakan tokenisasi pencocokan persis, karena indeks sekunder tidak mendukung penelusuran teks lengkap):
CREATE SEARCH INDEX AlbumsSearchIndex
ON Albums(AlbumName_Token)
ORDER BY ReleaseTimestamp DESC;
Urutan pengurutan indeks penelusuran harus sesuai dengan persyaratan berikut:
- Hanya gunakan kolom
INT64
untuk urutan pengurutan indeks penelusuran. Kolom yang memiliki ukuran arbitrer menggunakan terlalu banyak resource dalam indeks penelusuran karena Spanner perlu menyimpan docid di samping setiap token. Secara khusus, kolom urutan pengurutan tidak dapat menggunakan jenisTIMESTAMP
karenaTIMESTAMP
menggunakan presisi nanosekon yang tidak sesuai dengan bilangan bulat 64-bit. Kolom urutan pengurutan tidak boleh berupa
NULL
. Ada dua cara untuk memenuhi persyaratan ini:- Deklarasikan kolom urutan pengurutan sebagai
NOT NULL
. - Konfigurasikan indeks untuk mengecualikan nilai NULL.
- Deklarasikan kolom urutan pengurutan sebagai
Stempel waktu sering digunakan untuk menentukan urutan pengurutan. Praktik yang umum adalah menggunakan mikrodetik sejak epoch Unix untuk stempel waktu tersebut.
Aplikasi biasanya mengambil data terbaru terlebih dahulu menggunakan indeks penelusuran yang diurutkan dalam urutan menurun.
Indeks penelusuran yang difilter dengan NULL
Indeks penelusuran dapat menggunakan sintaksis WHERE column IS NOT NULL
untuk
mengecualikan baris tabel dasar. Pemfilteran NULL dapat diterapkan ke kunci partisi, kolom urutan
pengurutan, 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 penelusuran. Untuk informasi selengkapnya, lihat persyaratan kueri SQL.
Gunakan pemfilteran NULL pada kolom yang dihasilkan untuk mengecualikan baris berdasarkan kriteria arbitrer. Untuk mengetahui informasi selengkapnya, lihat Membuat indeks parsial menggunakan kolom yang dihasilkan.
Langkah selanjutnya
- Pelajari tokenisasi dan tokenizer Spanner.
- Pelajari indeks numerik.
- Pelajari partisi indeks.