Halaman ini menjelaskan fungsi SEARCH
dan mode kueri yang ditingkatkan, yang
yang digunakan untuk melakukan penelusuran teks lengkap
kueri pada tabel Spanner.
Mengkueri indeks penelusuran
Spanner menyediakan
SEARCH
untuk kueri indeks pencarian. Fungsi SEARCH
memerlukan dua argumen:
- Nama indeks penelusuran
- Kueri
Fungsi SEARCH
hanya berfungsi saat indeks penelusuran ditentukan. SEARCH
dapat digabungkan dengan konstruksi SQL arbitrer, seperti filter,
agregasi, atau penggabungan.
Kueri berikut menggunakan fungsi SEARCH
untuk menampilkan semua album yang memiliki
friday
atau monday
di judul:
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'friday OR monday')
Bahasa kueri
Argumen kedua fungsi SEARCH
adalah bahasa khusus domain (DSL)
disebut rquery. Bahasa rquery mirip dengan yang biasa digunakan pengguna internet di google.com:
- Beberapa istilah menyiratkan
AND
. Misalnya, "Big Time" setara denganbig AND time
. Operasi
OR
menyiratkan disjungsi antara dua istilah, sepertibig OR time
. PernyataanSEARCH(tl, 'big time OR fast car')
setara dengan:SEARCH(tl, 'big') AND (SEARCH(tl, 'time') OR SEARCH(tl, 'fast')) AND SEARCH(tl, 'cat');
OR
hanya berlaku untuk dua istilah yang berdekatan. Misalnya, pencarian ekspresihappy friday OR monday
menelusuri semua dokumen yang memiliki istilahhappy
dan istilahfriday
ataumonday
.Tanda kutip ganda berarti penelusuran frasa. Misalnya, kueri
"big cat"
cocok dengan "Saya punya kucing besar", tetapi tidak cocok dengan "Kucing saya besar".Operator
AROUND
cocok dengan istilah yang berada dalam jarak tertentu sama lain. Misalnya, kueri rbig AROUND cat
cocok dengan "kucing besar, putih, dan lembut", tetapi tidak cocok dengan "anjing besar duduk di samping kucing kecil". Setelan defaultnya adalah mencocokkan istilah yang dipisahkan oleh maksimal lima posisi. Kepada sesuaikan jarak, teruskan argumen ke operatorAROUND
. Spanner mendukung dua sintaksis untukAROUND
:big AROUND(10) cat
big AROUND 10 cat
Operator
AROUND
, jika digunakan sebagai bagian dari frasa, dapat cocok dengan istilah yang berada dalam jarak tertentu satu sama lain, dan dalam urutan yang sama ( defaultnya adalah lima token). Misalnya, stringbig AROUND cat
cocok "kucing putih besar dan berbulu", tetapi bukan "kucing itu besar".Negasi token tunggal dinyatakan dengan tanda hubung (
-
). Misalnya-dog
cocok dengan semua dokumen yang tidak berisi istilahdog
.Tanda baca umumnya diabaikan. Misalnya, "Waktu Terbaik!" setara dengan "Waktu yang Tepat".
Penelusuran tidak peka huruf besar/kecil. Misalnya, "Big Time" cocok dengan "big time".
Operator
The OR
danAROUND
peka huruf besar/kecil. Karakter pipa (|
) adalah pintasan untukOR
.
Cara kerja bahasa kueri
Bahasa rquery mengikuti aturan yang sama dengan tokenizer teks biasa saat memisahkan string input menjadi istilah yang berbeda. Hal ini mencakup segmentasi bahasa Asia.
Banyak aplikasi menyediakan cara bagi pengguna untuk memasukkan kueri penelusuran ke
kotak penelusuran. Cara termudah untuk mengintegrasikan kueri
pengguna akhir tersebut adalah dengan mengirim
input pengguna secara langsung ke dalam fungsi SEARCH
.
Tabel berikut menjelaskan arti berbagai string kueri:
rquery | Penjelasan |
---|---|
Big Cat |
Mencocokkan dokumen yang berisi kedua istilah "besar" dan "cat". |
cat OR dog |
Cocok dengan dokumen yang berisi setidaknya salah satu istilah "cat" dan "dog". |
-cat |
Mencocokkan semua dokumen yang tidak berisi istilah "cat". |
"big dog" -"big cat" |
Mencocokkan dokumen yang berisi dua istilah "besar" yang berdekatan dan "dog", tetapi tidak berisi kata "big" yang berdekatan dan "cat". Misalnya, kueri ini cocok dengan "Saya punya besar dan kucing kecil", tetapi tidak cocok dengan "Saya punya besar dan kucing besar". |
cat|dog |
Ini sama dengan {i> cat OR dog<i}. |
and OR or |
Mencocokkan dokumen yang memiliki istilah "and" atau istilah "or" (operator OR harus dalam huruf besar) |
Mode kueri yang ditingkatkan
Selain penelusuran teks lengkap yang sepenuhnya berbasis token, Spanner
mendukung mode yang lebih kaya yang disebut enhance_query
. Jika diaktifkan, mode ini akan memperluas
kueri penelusuran untuk menyertakan lebih banyak varian token. Penulisan ulang ini meningkatkan penelusuran
perolehan.
Untuk mengaktifkan opsi ini, tetapkan argumen opsional enhance_query=>true
di bagian
fungsi SEARCH
. Misalnya, kueri penelusuran hotl cal
cocok dengan album
Hotel California
.
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'hotl cal', enhance_query=>true)
Mode enhance_query
adalah opsi waktu kueri. Token ini tidak memengaruhi tokenisasi.
Anda dapat menggunakan indeks penelusuran yang sama dengan atau tanpa enhance_query
.
Google terus meningkatkan kualitas algoritma penyempurnaan kueri. Sebagai
hasil, kueri dengan enhance_query == true
mungkin menghasilkan sedikit berbeda
hasil dari waktu ke waktu.
Saat mode enhance_query
diaktifkan, jumlah istilah dapat meningkat
yang dicari oleh fungsi SEARCH
dan dapat mengakibatkan
latensi yang rendah.
Misalnya, kueri berikut ini menggunakan waktu tunggu tiga detik dan akan gagal jika
enhance_query
tidak tersedia:
@{require_enhance_query=true, enhance_query_timeout_ms=3000}
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'cat', enhance_query=>true)
Persyaratan kueri SQL
Ada beberapa kondisi yang harus dipenuhi kueri SQL untuk menggunakan indeks penelusuran. Jika kondisi ini tidak terpenuhi, kueri akan menggunakan rencana kueri alternatif atau gagal jika tidak ada rencana alternatif.
Kueri harus memenuhi kondisi berikut:
- Fungsi
SEARCH
danSEARCH_SUBSTRING
memerlukan indeks penelusuran. Spanner tidak mendukung fungsi ini dalam kueri terhadap tabel dasar atau indeks sekunder. Kueri terhadap Indeks berpartisi harus memiliki semua kolom partisi yang dibatasi oleh kondisi kesetaraan di
WHERE
dari kueri.Misalnya, jika indeks penelusuran ditentukan sebagai
PARTITION BY x, y
, kueri harus memiliki konjungsi dalam klausulWHERE
darix = <parameter or constant> AND y = <parameter or constant>
. Indeks penelusuran tersebut tidak dipertimbangkan oleh pengoptimal kueri jika kondisi tersebut tidak ada.Semua
TOKENLIST
kolom yang direferensikan olehSEARCH
danSEARCH_SUBSTRING
operator harus diindeks dalam indeks penelusuran yang sama.Misalnya, perhatikan tabel dan definisi indeks berikut:
CREATE TABLE Albums ( AlbumId STRING(MAX) NOT NULL, AlbumTitle STRING(MAX), AlbumStudio STRING(MAX), AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN, AlbumStudio_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumStudio)) HIDDEN ) PRIMARY KEY(AlbumId); CREATE SEARCH INDEX AlbumsTitleIndex ON Albums(AlbumTitle_Tokens); CREATE SEARCH INDEX AlbumsStudioIndex ON Albums(AlbumStudio_Tokens);
Kueri berikut gagal karena tidak ada indeks penelusuran tunggal yang mengindeks
AlbumTitle_Tokens
danAlbumStudio_Tokens
:SELECT AlbumId FROM Albums WHERE SEARCH(AlbumTitle_Tokens, @p1) AND SEARCH(AlbumStudio_Tokens, @p2)
Jika kolom tata urutan nullable, skema dan kueri harus mengecualikan baris yang kolom tata urutannya adalah NULL. Lihat Tata urutan indeks penelusuran untuk mengetahui detailnya.
Jika indeks pencarian menggunakan filter NULL, kueri harus menyertakan Ekspresi pemfilteran NULL yang digunakan dalam indeks. Lihat Indeks penelusuran yang difilter NULL untuk mengetahui detailnya.
Indeks penelusuran tidak didukung dalam DML, DML terpartisi, dan .
Indeks pencarian biasanya digunakan dalam transaksi hanya baca. Jika persyaratan aplikasi memungkinkan hasil yang kedaluwarsa, sebaiknya jalankan penelusuran kueri dengan durasi penghentian 10 detik atau lebih lama. Untuk selengkapnya informasi, lihat Membaca data yang sudah tidak berlaku. Ini adalah sangat berguna untuk kueri pencarian besar yang menyebar ke beberapa Paxos grup.
Indeks penelusuran tidak direkomendasikan di transaksi baca-tulis. Selama eksekusi, kueri penelusuran mengunci seluruh partisi indeks; sebagai menghasilkan tingkat kueri penelusuran yang tinggi dalam transaksi baca-tulis dapat konflik kunci yang menyebabkan lonjakan latensi. Secara default, indeks penelusuran tidak dipilih secara otomatis dalam transaksi baca-tulis. Jika kueri dipaksa untuk menggunakan indeks penelusuran dalam transaksi baca-tulis yang gagal secara {i>default<i}. Ini perilaku ini dapat diganti dengan Petunjuk tingkat pernyataan
@{ALLOW_SEARCH_INDEXES_IN_TRANSACTION=TRUE}
(tetapi kueri masih rentan terhadap konflik kunci).
Setelah kondisi kelayakan indeks terpenuhi, pengoptimal kueri akan mencoba
mempercepat kondisi kueri non-teks (seperti Rating > 4
). Jika indeks penelusuran
tidak menyertakan kolom TOKENLIST
yang sesuai, kondisinya tidak
dipercepat dan tetap merupakan kondisi residu.
Parameter kueri
kueri dan parameter lain seperti OFFSET
ditetapkan sebagai literal atau
parameter kueri.
Sebaiknya gunakan parameter kueri daripada literal string. Diparameterisasi
kueri memiliki kueri yang lebih baik
rasio hit cache yang mengakibatkan
latensi kueri yang lebih rendah dan penggunaan CPU
secara keseluruhan yang lebih rendah.
Misalnya, alih-alih menggunakan kueri seperti berikut:
SELECT AlbumId FROM Albums WHERE SEARCH(AlbumTitle_Tokens, 'cat')
gunakan sintaksis berikut:
SELECT AlbumId FROM Albums WHERE SEARCH(AlbumTitle_Tokens, @p)
Spanner menjalankan pengoptimal kueri pada teks SQL yang berbeda. Semakin sedikit teks SQL yang berbeda yang digunakan aplikasi, semakin sedikit waktu kueri pengoptimalan dipanggil.
Telusuri tata urutan indeks
Perilaku urutan pengurutan indeks penelusuran berbeda dengan indeks sekunder.
Misalnya, perhatikan 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 mungkin mendefinisikan indeks sekunder untuk mencari informasi dengan menggunakan
AlbumName
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;
Tata urutan indeks penelusuran harus sesuai dengan aturan berikut:
- Hanya gunakan
INT64
kolom untuk pengurutan urutan indeks pencarian. Kolom yang memiliki ukuran arbitrer menggunakan terlalu banyak resource di indeks penelusuran karena Spanner perlu menyimpan {i>docid<i} di sebelah setiap token. Secara khusus, kolom tata urutan tidak boleh menggunakan jenisTIMESTAMP
karenaTIMESTAMP
menggunakan presisi nanodetik yang tidak cocok dengan bilangan bulat 64-bit. Kolom tata urutan tidak boleh
NULL
. Ada dua cara untuk memenuhi hal ini persyaratan:- Deklarasikan kolom urutan pengurutan sebagai
NOT NULL
. - Konfigurasikan indeks untuk mengecualikan nilai NULL.
- Deklarasikan kolom urutan pengurutan sebagai
Dalam praktiknya, stempel waktu sering digunakan untuk menentukan tata urutan. Tanda umum adalah dengan menggunakan mikrodetik sejak Unix epoch untuk stempel waktu tersebut.
Aplikasi biasanya mengambil data terbaru terlebih dahulu menggunakan indeks pencarian yang diurutkan dalam urutan menurun.
Pemilihan indeks
Spanner biasanya memilih indeks yang paling efisien untuk kueri
menggunakan pemodelan berbasis biaya. Namun, petunjuk FORCE_INDEX
secara eksplisit menginstruksikan
Spanner untuk menggunakan indeks penelusuran tertentu. Misalnya,
berikut menunjukkan cara memaksa Spanner untuk menggunakan AlbumsIndex
:
SELECT AlbumId
FROM Albums @{FORCE_INDEX=AlbumsIndex}
WHERE SEARCH(AlbumTitle_Tokens, @p1)
Jika indeks penelusuran yang ditentukan tidak memenuhi syarat, gagal, meskipun ada indeks penelusuran lain yang memenuhi syarat.
Cuplikan di hasil penelusuran
Cuplikan adalah potongan teks yang diekstrak dari string tertentu yang memberi pengguna gambaran tentang isi hasil penelusuran, dan alasan hasil tersebut relevan dengan kueri mereka.
Misalnya, Gmail menggunakan cuplikan untuk menunjukkan bagian dari email yang cocok dengan kueri penelusuran:
Membuat database dalam membuat cuplikan memiliki beberapa manfaat:
- Kepraktisan: Anda tidak perlu menerapkan logika untuk membuat cuplikan dari kueri penelusuran.
- Efisiensi: Cuplikan mengurangi ukuran output dari server.
Fungsi SNIPPET
membuat cuplikan. Metode ini menampilkan bagian yang relevan dari
nilai string asli beserta posisi karakter yang akan ditandai. Tujuan
klien dapat memilih cara menampilkan cuplikan kepada pengguna akhir (misalnya,
menggunakan teks yang ditandai atau tebal). Fungsi SNIPPET
menghapus semua tag HTML
dari {i>string<i} asli.
Misalnya, kode berikut menggunakan SNIPPET
untuk mengambil teks dari AlbumTitle
:
SELECT AlbumId, SNIPPET(AlbumTitle, "Fast Car")
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "Fast Car")
Langkah selanjutnya
- Pelajari cara mengurutkan hasil penelusuran.
- Pelajari cara melakukan penelusuran substring.
- Pelajari cara memberi nomor halaman pada hasil penelusuran.
- Pelajari cara menggabungkan kueri teks lengkap dan non-teks.
- Pelajari cara menelusuri beberapa kolom.