建立及管理向量索引

本頁面說明如何建立及管理 Spanner 向量索引,這類索引會使用近似近鄰 (ANN) 搜尋和樹狀結構,加快資料的向量相似度搜尋速度。

Spanner 會使用專屬向量索引,加快近似近鄰 (ANN) 向量搜尋速度。這項索引採用 Google 研究團隊的可擴充最近鄰 (ScaNN),這是一種高效率的最近鄰演算法。

向量索引會使用樹狀結構來分割資料,並加快搜尋速度。Spanner 提供兩層和三層樹狀結構設定:

  • 兩層樹狀結構設定:葉節點 (num_leaves) 包含密切相關的向量群組,以及對應的質心。根層級包含所有葉節點的質心。
  • 三層樹狀結構設定:概念與兩層樹狀結構類似,但會導入額外的分支層 (num_branches),葉節點質心會進一步分割,形成根層級 (num_leaves)。

Spanner 會為您選擇索引。不過,如果您知道特定索引最適合,可以使用 FORCE_INDEX 提示,選擇最適合您用途的向量索引。

詳情請參閱VECTOR INDEX聲明

限制

建立向量索引

為提升向量索引的召回率和效能,建議您採取下列做法:

  • 將大部分含有嵌入的資料列寫入資料庫後,再建立向量索引。插入新資料後,您可能也需要定期重建向量索引。詳情請參閱「重建向量索引」。

  • 使用 STORING 子句將資料欄副本儲存在向量索引中。如果資料欄值儲存在向量索引中,Spanner 會在索引的葉層級執行篩選,以提升查詢效能。如果資料欄用於篩選條件,建議您儲存該資料欄。如要進一步瞭解如何在索引中使用 STORING,請參閱「建立僅供索引掃描的索引」。

建立資料表時,嵌入欄必須是 FLOAT32 (建議) 或 FLOAT64 資料類型的陣列,並具有 vector_length 註解,指出向量的維度。

下列 DDL 陳述式會建立 Documents 資料表,並包含向量長度的嵌入資料欄 DocEmbedding

CREATE TABLE Documents (
  UserId INT64 NOT NULL,
  DocId INT64 NOT NULL,
  Author STRING (1024),
  DocContents Bytes(MAX),
  DocEmbedding ARRAY<FLOAT32>(vector_length=>128) NOT NULL,
  NullableDocEmbedding ARRAY<FLOAT32>(vector_length=>128),
  WordCount INT64,
) PRIMARY KEY (DocId);

Documents 資料表填入資料後,您可以在 Documents 資料表上建立向量索引,其中包含兩層樹狀結構和 1000 個葉節點,並使用餘弦距離做為嵌入欄 DocEmbedding

CREATE VECTOR INDEX DocEmbeddingIndex
  ON Documents(DocEmbedding)
  STORING (WordCount)
  OPTIONS (distance_type = 'COSINE', tree_depth = 2, num_leaves = 1000);

如果資料表定義中未將嵌入資料欄標示為 NOT NULL,您必須在向量索引定義中,使用 WHERE COLUMN_NAME IS NOT NULL 子句宣告該資料欄,其中 COLUMN_NAME 是嵌入資料欄的名稱。如要使用餘弦距離,在可為空值的嵌入項目資料欄 NullableDocEmbedding 上建立含有三層樹狀結構和 1000000 個葉節點的向量索引,請執行下列操作:

CREATE VECTOR INDEX DocEmbeddingThreeLevelIndex
  ON Documents(NullableDocEmbedding)
  STORING (WordCount)
  WHERE NullableDocEmbedding IS NOT NULL
  OPTIONS (distance_type = 'COSINE', tree_depth = 3, num_branches=1000, num_leaves = 1000000);

篩選向量索引

您也可以建立經過篩選的向量索引,在資料庫中找出符合篩選條件的最相似項目。經過篩選的向量索引會選擇性地為符合指定篩選條件的資料列建立索引,進而提升搜尋效能。

在下列範例中,資料表 Documents2 有一個名為 Category 的資料欄。在向量搜尋中,我們想為「科技」類別建立索引,因此建立的產生資料欄會評估類別條件是否符合,如果不符合,則評估為 NULL

CREATE TABLE Documents2 (
  DocId INT64 NOT NULL,
  Category STRING(MAX),
  NullIfFiltered BOOL AS (IF(Category = 'Tech', TRUE, NULL)) HIDDEN,
  DocEmbedding ARRAY<FLOAT32>(vector_length=>128),
) PRIMARY KEY (DocId);

接著,我們建立含有篩選器的向量索引。TechDocEmbeddingIndex 向量索引只會為「技術」類別中的文件建立索引。

CREATE VECTOR INDEX TechDocEmbeddingIndex
  ON Documents2(DocEmbedding)
  STORING(NullIfFiltered)
  WHERE DocEmbedding IS NOT NULL AND NullIfFiltered IS NOT NULL
  OPTIONS (...);

當 Spanner 執行下列查詢 (其中包含與 TechDocEmbeddingIndex 相符的篩選條件) 時,系統會自動挑選 TechDocEmbeddingIndex,並透過 TechDocEmbeddingIndex 加速執行查詢。這項查詢只會搜尋「科技」類別中的文件。您也可以使用 {@FORCE_INDEX=TechDocEmbeddingIndex} 強制 Spanner 明確使用 TechDocEmbeddingIndex

SELECT *
FROM Documents2
WHERE DocEmbedding IS NOT NULL AND NullIfFiltered IS NOT NULL
ORDER BY APPROX_(....)
LIMIT 10;

後續步驟