分割搜尋索引

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 查詢最佳化工具會自動為每個查詢選取索引。

後續步驟