Ringkasan kueri

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 dengan big AND time.
  • Operasi OR menyiratkan disjungsi antara dua istilah, seperti big OR time. Pernyataan SEARCH(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 ekspresi happy friday OR monday menelusuri semua dokumen yang memiliki istilah happy dan istilah friday atau monday.

  • 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 r big 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 operator AROUND. Spanner mendukung dua sintaksis untuk AROUND:

    • 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, string big 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 istilah dog.

  • 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 dan AROUND peka huruf besar/kecil. Karakter pipa (|) adalah pintasan untuk OR.

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 dan SEARCH_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 klausul WHERE dari x = <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 oleh SEARCH dan SEARCH_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 dan AlbumStudio_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:

  1. 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 jenis TIMESTAMP karena TIMESTAMP menggunakan presisi nanodetik yang tidak cocok dengan bilangan bulat 64-bit.
  2. Kolom tata urutan tidak boleh NULL. Ada dua cara untuk memenuhi hal ini persyaratan:

    1. Deklarasikan kolom urutan pengurutan sebagai NOT NULL.
    2. Konfigurasikan indeks untuk mengecualikan nilai NULL.

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:

Daftar cuplikan

Membuat database dalam membuat cuplikan memiliki beberapa manfaat:

  1. Kepraktisan: Anda tidak perlu menerapkan logika untuk membuat cuplikan dari kueri penelusuran.
  2. 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