查詢總覽

本頁面說明 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 提供兩種全文搜尋模式:基本權杖式搜尋和更進階的 enhance_query 模式。啟用後,enhance_query 會擴充搜尋查詢,納入相關字詞和同義詞,提高找到相關結果的機率。

如要啟用這個選項,請在 SEARCH 函式中設定選用引數 enhance_query=>true。舉例來說,搜尋查詢 hotl cal 會比對到專輯 Hotel California

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'hotl cal', enhance_query=>true)

PostgreSQL

SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'hotl cal', enhance_query=>true)

enhance_query 模式是查詢時間選項。這不會影響權杖化。 無論是否使用 enhance_query,您都可以使用相同的搜尋索引。

Google 會持續改良查詢強化演算法,因此,隨著時間經過,使用 enhance_query == true 的查詢可能會產生略有不同的結果。

啟用 enhance_query 模式後,SEARCH 函式搜尋的字詞數量可能會增加,導致延遲時間稍微延長。

舉例來說,下列查詢會使用三秒逾時,如果 enhance_query 無法使用,查詢就會失敗:

GoogleSQL

@{require_enhance_query=true, enhance_query_timeout_ms=3000}
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'fast car', enhance_query=>true)

PostgreSQL

/*@require_enhance_query=true, enhance_query_timeout_ms=3000*/
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'fast car', enhance_query=>true)

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

後續步驟