分區搜尋索引

Spanner 支援未分割和已分割的搜尋索引。本頁說明如何在 Spanner 中建立分割搜尋索引。

如果在索引定義中省略 PARTITION BY 子句,系統就會建立未分割的索引。在未分割的索引中,查詢需要從所有索引分割項目讀取。這會限制全文搜尋查詢的潛在可擴充性。

另一方面,分區索引會將索引細分為較小的單位,每個獨特分區各有一個。查詢只能在 WHERE 子句中指定的等式條件中,一次搜尋單一區隔。針對已分區索引的查詢通常比針對未分區索引的查詢更有效率,因為 Spanner 只需要讀取單一分區的資料。搜尋索引的分割方式類似次要索引的索引鍵前置字串。

舉例來說,假設資料庫中有 1,000,000 個 SingerIds,以及以下兩個索引:

GoogleSQL

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  SingerId STRING(MAX) NOT NULL,
  ReleaseTimestamp INT64 NOT NULL,
  AlbumTitle STRING(MAX),
  AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN,
  SingerId_Tokens TOKENLIST AS (TOKEN(SingerId)) HIDDEN
) PRIMARY KEY(SingerId, AlbumId);

CREATE SEARCH INDEX AlbumsUnpartitionedIndex
ON Albums(AlbumTitle_Tokens, SingerId_Tokens);

CREATE SEARCH INDEX AlbumsIndexBySingerId
ON Albums(AlbumTitle_Tokens)
PARTITION BY SingerId;

PostgreSQL

CREATE TABLE albums (
  albumid character varying NOT NULL,
  singerid character varying NOT NULL,
  releasetimestamp bigint NOT NULL,
  albumtitle character varying,
  albumtitle_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN,
  singerid_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.token(singerid)) VIRTUAL HIDDEN,
PRIMARY KEY(singerid, albumid));

CREATE SEARCH INDEX albumsunpartitionedindex
ON albums(albumtitle_tokens, singerid_tokens);

CREATE SEARCH INDEX albumsindexbysingerid
ON albums(albumtitle_tokens)
PARTITION BY singerid;

以下查詢會選取 AlbumsIndexBySingerId 索引,因為它只會搜尋單一歌手的資料。這類查詢通常會使用較少的資源。

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SingerId = "singer1"
AND SEARCH(AlbumTitle_Tokens, 'happy')

PostgreSQL

SELECT albumid
FROM albums
WHERE singerid = 'singer1'
AND spanner.search(albumtitle_tokens, 'happy')

您也可以強制使用 AlbumsUnpartitionedIndex 來傳回相同結果的查詢。不過,這會使用更多資源,因為查詢需要存取所有索引分割項目,並篩選所有專輯的所有歌手,以便找出「happy」符記,而非只篩選與歌手 singer1 對應的分割項目。

不過,應用程式有時需要搜尋所有專輯,而非特定歌手的專輯。在下列情況下,您必須使用未分割的索引:

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'piano concerto 1')

PostgreSQL

SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'piano concerto 1')

一般建議使用最精細的分區細目,以便實用且適合查詢。舉例來說,如果應用程式會查詢電子郵件信箱,且每項查詢都限制在特定信箱中,請根據信箱 ID 劃分搜尋索引。不過,如果查詢需要搜尋所有信箱,則不分割索引會更適合。

某些應用程式可能需要多種區隔策略,以滿足特定搜尋需求。舉例來說,商品目錄管理系統可能需要支援依產品類型或製造商篩選的查詢。此外,某些應用程式可能需要多個預先排序,例如依據建立或修改時間排序。在這些情況下,建議您建立多個搜尋索引,並針對各個查詢進行最佳化。Spanner 查詢最佳化器會自動為每個查詢選取索引。

後續步驟