查詢總覽

本頁面說明 SEARCH 函式及其各種進階功能,這些功能用於對 Spanner 表格執行全文搜尋查詢。

查詢搜尋索引

Spanner 提供 SEARCH 函式,用於搜尋索引查詢。舉例來說,使用者在應用程式的搜尋方塊中輸入文字,應用程式會將使用者輸入的內容直接傳送至 SEARCH 函式。SEARCH 函式隨後會使用搜尋索引尋找該文字。

SEARCH 函式需要兩個引數:

  • 搜尋索引名稱
  • 搜尋查詢

只有在定義搜尋索引時,SEARCH 函式才會運作。SEARCH 函式可與任何任意 SQL 建構體合併,例如篩選器、匯總或聯結。

SEARCH 函式無法與交易查詢搭配使用。

下列查詢使用 SEARCH 函式,傳回標題中含有 fridaymonday 的所有專輯:

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'friday OR monday')

PostgreSQL

本範例使用 spanner.search

SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'friday OR monday')

搜尋查詢

根據預設,搜尋查詢會使用原始搜尋查詢語法。您可以使用 SEARCH dialect 引數指定替代語法。

rquery 方言

預設方言為「原始搜尋查詢」。Spanner 使用名為 rquery 的特定領域語言 (DSL)。

將輸入的搜尋查詢拆分為不同字詞時,rquery 語言會遵循與純文字權杖化工具相同的規則。包括亞洲語言的區隔。

如要瞭解如何使用 rquery,請參閱 rquery 語法

words dialect

「dialect」一詞類似於「rquery」,但更簡單。不會使用任何特殊運算子。舉例來說,OR 會被視為搜尋字詞,而非不相交運算子。雙引號會視為標點符號,而非片語搜尋,因此系統會忽略雙引號。

使用「dialect」一詞時,AND 會隱含套用至所有字詞,且必須在比對期間使用。將輸入的搜尋查詢拆分為字詞時,系統會遵循與純文字權杖化工具相同的規則。

如要瞭解如何使用「words」方言,請參閱「words」語法

words_phrase 方言

words_phrase 方言不會使用任何特殊運算子,所有字詞都會視為片語,也就是字詞必須相鄰,且順序與指定順序相同。

與 rquery 相同,words_phrase 方言在將輸入的搜尋查詢分割為字詞時,會遵循與純文字權杖化工具相同的規則。

如要瞭解如何使用 words_phrase 方言,請參閱 words phrase 語法

擴大搜尋查詢範圍,增加相關結果

您可以運用 Spanner 的進階功能,擴大搜尋查詢範圍,納入相關字詞、同義詞和拼字修正,提高找到相關結果的機率。這些攻擊行動包括:

詳情請參閱「使用查詢強化功能搜尋」。

SQL 查詢規定

SQL 查詢必須符合多項條件,才能使用搜尋索引。 如未滿足這些條件,查詢會使用替代查詢計畫,或在沒有替代計畫的情況下失敗。

查詢必須符合下列條件:

  • SEARCH 函式SEARCH_SUBSTRING 函式需要搜尋索引。針對基本資料表或次要索引的查詢,Spanner 不支援這些函式。

  • 已分割的索引必須在查詢的 WHERE 子句中,將所有分割資料欄繫結至等號條件。

    舉例來說,如果搜尋索引定義為 PARTITION BY x, y,查詢的 x = <parameter or constant> AND y = <parameter or constant> WHERE 子句就必須有連詞。如果缺少這類條件,查詢最佳化工具就不會考慮該搜尋索引。

  • SEARCHSEARCH_SUBSTRING 運算子參照的所有 TOKENLIST 欄都必須編入同一個搜尋索引。

    舉例來說,請參考下列資料表和索引定義:

    GoogleSQL

    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);
    

    PostgreSQL

    CREATE TABLE albums (
        albumid character varying NOT NULL,
        albumtitle character varying,
        albumstudio character varying,
        albumtitle_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN,
        albumstudio_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumstudio)) VIRTUAL HIDDEN,
    PRIMARY KEY(albumid));
    
    CREATE SEARCH INDEX albumstitleindex ON albums(albumtitle_tokens);
    CREATE SEARCH INDEX albumsstudioindex ON albums(albumstudio_tokens);
    

    下列查詢會失敗,因為沒有單一搜尋索引可同時為 AlbumTitle_TokensAlbumStudio_Tokens 建立索引:

    GoogleSQL

    SELECT AlbumId
    FROM Albums
    WHERE SEARCH(AlbumTitle_Tokens, @p1)
        AND SEARCH(AlbumStudio_Tokens, @p2)
    

    PostgreSQL

    這個範例使用查詢參數 $1$2,分別繫結至「fast car」和「blue note」。

    SELECT albumid
    FROM albums
    WHERE spanner.search(albumtitle_tokens, $1)
        AND spanner.search(albumstudio_tokens, $2)
    
  • 如果排序順序資料欄可為空值,結構定義和查詢都必須排除排序順序資料欄為空值的資料列。詳情請參閱「搜尋索引排序順序」。

  • 如果搜尋索引經過 NULL 篩選,查詢必須包含索引中使用的相同 NULL 篩選運算式。詳情請參閱「已篩除 NULL 的搜尋索引」。

  • DML、分區 DML 或分區查詢不支援搜尋索引搜尋函式

  • 搜尋索引搜尋函式通常用於唯讀交易。如果應用程式需求允許過時結果,您或許可以執行搜尋查詢,並將過時時間長度設為 10 秒以上,藉此縮短延遲時間。詳情請參閱「讀取過時資料」。這項功能特別適合用於搜尋查詢,可分散至多個索引分割。

建議不要在讀寫交易中使用搜尋索引搜尋函式。執行期間,搜尋查詢會鎖定整個索引分區;因此,讀寫交易中的搜尋查詢率偏高可能會導致鎖定衝突,進而造成延遲尖峰。根據預設,系統不會在讀寫交易中自動選取搜尋索引。如果查詢在讀取/寫入交易中強制使用搜尋索引,預設會失敗。如果查詢包含任何搜尋函式,也會失敗。您可以使用 GoogleSQL @{ALLOW_SEARCH_INDEXES_IN_TRANSACTION=TRUE} 陳述式層級提示覆寫此行為 (但查詢仍容易發生鎖定衝突)。

符合索引資格條件後,查詢最佳化工具會嘗試加速處理非文字查詢條件 (例如 Rating > 4)。如果搜尋索引未包含適當的 TOKENLIST 欄,系統就不會加速處理條件,條件仍會是剩餘條件

查詢參數

搜尋查詢引數可指定為常值或查詢參數。如果引數允許查詢參數值,建議使用查詢參數進行全文搜尋,而非字串常值。

指數選擇

Spanner 通常會使用以成本為準的建模方式,為查詢選取最有效率的索引。不過,FORCE_INDEX 提示會明確指示 Spanner 使用特定搜尋索引。舉例來說,以下說明如何強制 Spanner 使用 AlbumsIndex

GoogleSQL

SELECT AlbumId
FROM Albums @{FORCE_INDEX=AlbumsIndex}
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")

PostgreSQL

SELECT albumid
FROM albums/*@force_index=albumsindex*/
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')

如果指定的搜尋索引不符合資格,即使有其他符合資格的搜尋索引,查詢也會失敗。

搜尋結果中的摘要

網頁摘要是從指定字串擷取的文字片段,可讓使用者瞭解搜尋結果的內容,以及結果與查詢內容的相關性。

舉例來說,Gmail 會使用摘要來指出電子郵件中符合搜尋查詢的部分:

程式碼片段清單

讓資料庫產生程式碼片段有幾項優點:

  1. 便利性:您不需要實作邏輯,即可從搜尋查詢產生摘要。
  2. 效率:程式碼片段可縮減伺服器的輸出大小。

SNIPPET 函式會建立程式碼片段。這個函式會傳回原始字串值的相關部分,以及要醒目顯示的字元位置。然後,用戶端可以選擇如何向使用者顯示程式碼片段 (例如使用醒目顯示或粗體文字)。

舉例來說,下列程式碼會使用 SNIPPETAlbumTitle 擷取文字:

GoogleSQL

SELECT AlbumId, SNIPPET(AlbumTitle, "Fast Car")
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "Fast Car")

PostgreSQL

本範例使用 spanner.snippet

SELECT albumid, spanner.snippet(albumtitle, 'Fast Car')
FROM albums
WHERE spanner.search(albumtitle_tokens, 'Fast Car')

後續步驟