管理向量索引

本文說明如何建立及管理向量索引,加快向量搜尋速度。

向量索引是一種資料結構,可讓 VECTOR_SEARCH 函式更有效率地執行,特別是在大型資料集上。使用索引時,VECTOR_SEARCH 會採用近似最鄰近 (ANN) 演算法,以減少查詢延遲和運算成本。雖然 ANN 會引入某種程度的近似值,也就是說喚回度可能不會達到 100%,但效能提升通常對大多數應用程式都有優勢。

角色和權限

如要建立向量索引,您必須在要建立索引的資料表上,具備 bigquery.tables.createIndex IAM 權限。如要捨棄向量索引,您需要 bigquery.tables.deleteIndex 權限。下列每個預先定義的 IAM 角色都包含使用向量索引所需的權限:

  • BigQuery 資料擁有者 (roles/bigquery.dataOwner)
  • BigQuery 資料編輯者 (roles/bigquery.dataEditor)

選擇向量索引類型

BigQuery 提供兩種向量索引類型:IVFTreeAH,每種索引都支援不同的用途。BigQuery 支援批次處理,可透過 VECTOR_SEARCH 函式處理多列輸入資料,進行向量搜尋。如果是小批量的查詢,建議使用 IVF 索引。對於大型查詢批次,建議使用以 Google ScaNN 演算法建構的 TreeAH 索引。

IVF 指數

IVF 是反向檔案索引,會使用 k-means 演算法將向量資料分群,然後根據這些叢集劃分向量資料。VECTOR_SEARCH 函式可以使用這些分區,減少判斷結果時需要讀取的資料量。

TreeAH 索引

TreeAH 索引類型得名於樹狀結構,以及不對稱雜湊 (AH) 的使用。不對稱雜湊是基礎 ScaNN 演算法的核心量化技術。TreeAH 索引的運作方式如下:

  1. 基礎資料表會分割成較小且易於管理的分片。
  2. 系統會訓練叢集模型,並從 CREATE VECTOR INDEX 陳述式的 tree_ah_options 引數中,衍生叢集數量。leaf_node_embedding_count
  3. 系統會使用產品量化技術壓縮向量,減少記憶體用量。壓縮後的向量會儲存在索引表中,取代原始向量,藉此縮減向量索引的大小。
  4. VECTOR_SEARCH 函式執行時,系統會使用非對稱雜湊,有效率地計算每個查詢向量的候選清單,並針對近似距離計算進行硬體最佳化。然後使用確切的嵌入內容重新評分和排序這些候選項目。

TreeAH 演算法經過最佳化調整,可處理數百個以上的查詢向量,適合用於批次查詢。使用產品量化可大幅減少延遲時間和成本,與 IVF 相比,可能減少數個數量級。不過,由於負擔增加,當查詢向量數量較少時,IVF 演算法可能更適合。

如果您的用途符合下列條件,建議嘗試使用 TreeAH 索引類型:

  • 表格包含的列數不得超過 2 億列。

  • 您經常執行大型批次查詢,其中包含數百個以上的查詢向量。

如果是使用 TreeAH 索引類型的小批次查詢,VECTOR_SEARCH 可能會還原為暴力搜尋。發生這種情況時,系統會提供 IndexUnusedReason,說明向量索引未使用的原因。

建立 IVF 向量索引

如要建立 IVF 向量索引,請使用CREATE VECTOR INDEX資料定義語言 (DDL) 陳述式:

  1. 前往「BigQuery」頁面

    前往 BigQuery

  2. 在查詢編輯器中執行下列 SQL 陳述式:

    如要建立 IVF 向量索引,請按照下列步驟操作:

    CREATE [ OR REPLACE ] VECTOR INDEX [ IF NOT EXISTS ] INDEX_NAME
    ON DATASET_NAME.TABLE_NAME(COLUMN_NAME)
    STORING(STORED_COLUMN_NAME [, ...])
    OPTIONS(index_type = 'IVF',
      distance_type = 'DISTANCE_TYPE',
      ivf_options = '{"num_lists":NUM_LISTS}')

    更改下列內容:

    • INDEX_NAME:您要建立的向量索引名稱。由於索引一律會與基本資料表建立在同一個專案和資料集中,因此名稱中不需要指定這些項目。
    • DATASET_NAME:包含資料表的資料集名稱。
    • TABLE_NAME:包含內嵌資料欄的資料表名稱。
    • COLUMN_NAME:包含嵌入資料的資料欄名稱。該欄的類型必須為 ARRAY<FLOAT64>。資料欄不得有任何子欄位。陣列中的所有元素都不得為 NULL,且資料欄中的所有值都必須具有相同的陣列維度。
    • STORED_COLUMN_NAME:資料表中的頂層資料欄名稱,用於儲存在向量索引中。欄類型不得為 RANGE。如果資料表有資料列層級存取政策,或資料欄有政策標記,系統就不會使用儲存的資料欄。如要瞭解如何啟用儲存的資料欄,請參閱儲存資料欄和預先篩選
    • DISTANCE_TYPE:指定使用這個索引執行向量搜尋時,要使用的預設距離類型。支援的值為 EUCLIDEANCOSINEDOT_PRODUCT。預設為 EUCLIDEAN

      建立索引時一律會使用 EUCLIDEAN 距離進行訓練,但 VECTOR_SEARCH 函式中使用的距離可能不同。

      如果您為 VECTOR_SEARCH 函式的 distance_type 引數指定值,系統會使用該值,而非 DISTANCE_TYPE 值。

    • NUM_LISTSINT64 值,指定 IVF 索引叢集數量,然後將向量資料分割成這些叢集。這個值不得超過 5,000。在建立索引期間,向量會指派至最接近的叢集質心所對應的清單。如果省略這個引數,BigQuery 會根據資料特徵判斷預設值。預設值適用於大多數用途。

      NUM_LISTS 可控制查詢調整的精細程度。 值越高,建立的清單就越多,因此您可以將 VECTOR_SEARCH 函式的 fraction_lists_to_search 選項設為掃描較小百分比的索引。舉例來說,掃描 100 個清單中的 1%,而不是掃描 10 個清單中的 10%。這樣一來,就能更精細地控制搜尋速度和喚回率,但索引成本會稍微提高。請根據您需要多精確地調整查詢範圍,設定這個引數值。

以下範例會在 my_tableembedding 資料欄上建立向量索引:

CREATE TABLE my_dataset.my_table(embedding ARRAY<FLOAT64>);

CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding)
OPTIONS(index_type = 'IVF');

以下範例會在 my_tableembedding 欄上建立向量索引,並指定要使用的距離類型和 IVF 選項:

CREATE TABLE my_dataset.my_table(embedding ARRAY<FLOAT64>);

CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding)
OPTIONS(index_type = 'IVF', distance_type = 'COSINE',
ivf_options = '{"num_lists": 2500}')

建立 TreeAH 向量索引

如要建立 TreeAH 向量索引,請使用CREATE VECTOR INDEX資料定義語言 (DDL) 陳述式:

  1. 前往「BigQuery」頁面

    前往 BigQuery

  2. 在查詢編輯器中執行下列 SQL 陳述式:

    CREATE [ OR REPLACE ] VECTOR INDEX [ IF NOT EXISTS ] INDEX_NAME
    ON DATASET_NAME.TABLE_NAME(COLUMN_NAME)
    STORING(STORED_COLUMN_NAME [, ...])
    OPTIONS(index_type = 'TREE_AH',
      distance_type = 'DISTANCE_TYPE',
      tree_ah_options = '{"leaf_node_embedding_count":LEAF_NODE_EMBEDDING_COUNT,
        "normalization_type":"NORMALIZATION_TYPE"}')

    更改下列內容:

    • INDEX_NAME:您要建立的向量索引名稱。由於索引一律會與基本資料表建立在同一個專案和資料集中,因此不需要在名稱中指定這些項目。
    • DATASET_NAME:包含資料表的資料集名稱。
    • TABLE_NAME:包含內嵌資料欄的資料表名稱。
    • COLUMN_NAME:包含嵌入資料的資料欄名稱。該欄的類型必須為 ARRAY<FLOAT64>。資料欄不得有任何子欄位。陣列中的所有元素都不得為 NULL,且資料欄中的所有值都必須具有相同的陣列維度。
    • STORED_COLUMN_NAME:資料表中的頂層資料欄名稱,用於儲存在向量索引中。欄類型不得為 RANGE。如果資料表有資料列層級存取政策,或資料欄有政策標記,系統就不會使用儲存的資料欄。如要瞭解如何啟用儲存的資料欄,請參閱儲存資料欄和預先篩選
    • DISTANCE_TYPE:選用引數,用於指定使用這個索引執行向量搜尋時,要使用的預設距離類型。支援的值為 EUCLIDEANCOSINEDOT_PRODUCT。預設為 EUCLIDEAN

      建立索引時一律會使用 EUCLIDEAN 距離進行訓練,但 VECTOR_SEARCH 函式中使用的距離可能不同。

      如果您為 VECTOR_SEARCH 函式的 distance_type 引數指定值,系統會使用該值,而非 DISTANCE_TYPE 值。

    • LEAF_NODE_EMBEDDING_COUNTINT64 值,大於或等於 500,指定 TreeAH 演算法建立的樹狀結構中,每個葉節點的向量概略數量。TreeAH 演算法會將整個資料空間劃分成多個清單,每個清單大約包含 LEAF_NODE_EMBEDDING_COUNT 個資料點。值越小,建立的清單越多,但資料點越少;值越大,建立的清單越少,但資料點越多。預設值為 1,000,適用於大多數資料集。

    • NORMALIZATION_TYPESTRING 值。支援的值為 NONEL2。預設值為 NONE。系統會在處理基本資料表資料和查詢資料前進行正規化,但不會修改 TABLE_NAME 中的嵌入資料欄 COLUMN_NAME。視資料集、嵌入模型和 VECTOR_SEARCH 期間使用的距離類型而定,正規化嵌入可能會提高召回率。

下列範例會在 my_tableembedding 資料欄上建立向量索引,並指定要使用的距離類型和 TreeAH 選項:

CREATE TABLE my_dataset.my_table(id INT64, embedding ARRAY<FLOAT64>);

CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding)
OPTIONS (index_type = 'TREE_AH', distance_type = 'EUCLIDEAN',
tree_ah_options = '{"normalization_type": "L2"}');

篩選

以下各節說明前置和後置篩選器如何影響向量搜尋結果,以及如何使用向量索引中的儲存資料欄和分區進行前置篩選。

前置篩選器和後置篩選器

在 BigQuery VECTOR_SEARCH 作業中,預先篩選和後續篩選都會根據與向量嵌入項目相關聯的中繼資料欄套用條件,藉此精確搜尋結果。瞭解兩者的差異、實作方式和影響,有助於提升查詢效能、降低成本及提高準確度。

預先篩選和後續篩選的定義如下:

  • 預先篩選:在近似近鄰 (ANN) 搜尋對候選向量執行距離計算前,套用篩選條件。這會縮小搜尋時考量的向量集。 因此,預先篩選通常會縮短查詢時間並降低運算成本,因為 ANN 搜尋評估的候選項目較少。
  • 後續篩選:在 ANN 搜尋找出初始的最近鄰後,套用篩選條件。top_k這會根據指定條件調整最終結果集。

WHERE 子句的位置會決定篩選器是前置篩選器還是後置篩選器。

如要建立前置篩選器,查詢的 WHERE 子句必須套用至 VECTOR_SEARCH 函式的基本資料表引數。述詞必須套用至儲存的資料欄,否則會變成後置篩選器。

以下範例說明如何建立前置篩選器:

-- Pre-filter on a stored column. The index speeds up the query.
SELECT *
FROM
  VECTOR_SEARCH(
    (SELECT * FROM my_dataset.my_table WHERE type = 'animal'),
    'embedding',
    TABLE my_dataset.my_testdata);

-- Filter on a column that isn't stored. The index is used to search the
-- entire table, and then the results are post-filtered. You might see fewer
-- than 5 matches returned for some embeddings.
SELECT query.test_id, base.type, distance
FROM
  VECTOR_SEARCH(
    (SELECT * FROM my_dataset.my_table WHERE id = 123),
    'embedding',
    TABLE my_dataset.my_testdata,
    top_k => 5);

-- Use pre-filters with brute force. The data is filtered and then searched
-- with brute force for exact results.
SELECT query.test_id, base.type, distance
FROM
  VECTOR_SEARCH(
    (SELECT * FROM my_dataset.my_table WHERE id = 123),
    'embedding',
    TABLE my_dataset.my_testdata,
    options => '{"use_brute_force":true}');

如要建立後置篩選器,查詢的 WHERE 子句必須套用至 VECTOR_SEARCH 函式外部,才能篩選搜尋傳回的結果。

以下範例說明如何建立後篩選器:

-- Use post-filters. The index is used, but the entire table is searched and
-- the post-filtering might reduce the number of results.
SELECT query.test_id, base.type, distance
FROM
  VECTOR_SEARCH(
    TABLE my_dataset.my_table,
    'embedding',
    TABLE my_dataset.my_testdata,
    top_k => 5)
WHERE base.type = 'animal';

SELECT base.id, distance
FROM
  VECTOR_SEARCH(
    TABLE mydataset.base_table,
    'embedding',
    (SELECT embedding FROM mydataset.query_table),
    top_k => 10
  )
WHERE type = 'document' AND year > 2022

使用後續篩選或指定的基本資料表篩選器參照非儲存資料欄,進而做為後續篩選器時,如果述詞具有選擇性,最終結果集可能包含少於 top_k 個資料列,甚至可能沒有資料列。如果篩選後需要特定數量的結果,請考慮在 VECTOR_SEARCH 呼叫中指定較大的 top_k 值或增加 fraction_lists_to_search 值。

在某些情況下,尤其是當預先篩選條件非常嚴格時,預先篩選也可以縮減結果集的大小。如果發生這種情況,請嘗試在 VECTOR_SEARCH 呼叫中增加 fraction_lists_to_search 值。

使用已儲存的資料欄預先篩選

如要進一步提升向量索引的效率,可以指定要儲存在向量索引中的基本資料表資料欄。使用儲存的資料欄可透過下列方式,最佳化呼叫 VECTOR_SEARCH 函式的查詢:

  • 您可以對查詢陳述式呼叫 VECTOR_SEARCH 函式,該陳述式會使用 WHERE 子句預先篩選基本資料表,不必搜尋整個資料表。如果資料表有索引,且您只篩選儲存的資料欄,BigQuery 會先篩選資料,再使用索引搜尋較小的結果集,藉此最佳化查詢。如果篩選的資料欄未儲存,BigQuery 會在搜尋資料表後套用篩選器,也就是後置篩選器

  • VECTOR_SEARCH 函式會輸出名為 base 的結構體,其中包含基本資料表的所有資料欄。如果沒有儲存的資料欄,就可能需要耗費大量資源進行聯結,才能擷取 base 中儲存的資料欄。如果您使用 IVF 索引,且查詢只從 base 選取儲存的資料欄,BigQuery 就會最佳化查詢,以排除該聯結。如果是 TreeAH 索引,與主資料表的聯結不會移除。TreeAH 索引中儲存的資料欄僅用於預先篩選。

如要儲存資料欄,請在 CREATE VECTOR INDEX 陳述式的 STORING 子句中列出這些資料欄。儲存資料欄會增加向量索引的大小,因此最好只儲存最常使用或篩選的資料欄。

下列範例會建立含有儲存資料欄的向量索引,然後執行只選取儲存資料欄的向量搜尋查詢:

-- Create a table that contains an embedding.
CREATE TABLE my_dataset.my_table(embedding ARRAY<FLOAT64>, type STRING, creation_time DATETIME, id INT64);

-- Create a query table that contains an embedding.
CREATE TABLE my_dataset.my_testdata(embedding ARRAY<FLOAT64>, test_id INT64);

-- Create a vector index with stored columns.
CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding)
STORING (type, creation_time)
OPTIONS (index_type = 'IVF');

-- Select only stored columns from a vector search to avoid an expensive join.
SELECT query, base.type, distance
FROM
  VECTOR_SEARCH(
    TABLE my_dataset.my_table,
    'embedding'
    TABLE my_dataset.my_testdata);

儲存資料欄限制

  • 如果基底資料表中資料欄的模式、類型或結構定義有所變更,且該資料欄是向量索引中的儲存資料欄,則向量索引可能會有延遲,才會反映這項變更。在更新套用至索引前,向量搜尋查詢會使用主資料表中經過修改的儲存資料欄。
  • 如果您從具有儲存資料欄的索引資料表,選取 VECTOR_SEARCH 查詢的 query 輸出內容中 STRUCT 類型的資料欄,則整個查詢可能會失敗。

使用分區預先篩選

如果您要建立向量索引的資料表已分區,也可以選擇將向量索引分區。分割向量索引有下列優點:

  • 除了資料表分區,分區修剪也會套用至向量索引。當向量搜尋對分區資料欄的值套用符合的篩選器時,就會發生分區修剪。這樣一來,BigQuery 就能掃描符合篩選條件的分區,並略過其餘分區。分區修剪可降低 I/O 費用。如要進一步瞭解分區修剪,請參閱查詢分區資料表一文。
  • 如果預先依分區資料欄篩選,向量搜尋就比較不會遺漏結果。

您只能分割 TreeAH 向量索引。

只有在您使用預先篩選功能,將大部分的向量搜尋限制在幾個分區時,才建議對向量索引進行分區。

如要建立已分割的索引,請使用 CREATE VECTOR INDEX 陳述式的 PARTITION BY 子句。您在 CREATE VECTOR INDEX 陳述式中指定的 PARTITION BY 子句,必須與您要建立向量索引的表格 CREATE TABLE 陳述式中指定的 PARTITION BY 子句相同,如下例所示:

-- Create a date-partitioned table.
CREATE TABLE my_dataset.my_table(
  embeddings ARRAY
  id INT64,
  date DATE,
)
PARTITION BY date;

-- Create a partitioned vector index on the table.
CREATE VECTOR INDEX my_index ON my_dataset.my_table(embeddings)
PARTITION BY date
OPTIONS(index_type='TREE_AH', distance_type='COSINE');

如果資料表使用整數範圍或時間單位資料欄分區,分區資料欄會儲存在向量索引中,導致儲存空間費用增加。如果資料表資料欄同時用於 CREATE VECTOR INDEX 陳述式的 STORINGPARTITION BY 子句,系統只會儲存該資料欄一次。

如要使用向量索引分區,請在 VECTOR_SEARCH 陳述式的主資料表子查詢中,依分區資料欄進行篩選。在下列範例中,samples.items 資料表會依 produced_date 資料欄分區,因此 VECTOR_SEARCH 陳述式中的基本資料表子查詢會依 produced_date 資料欄進行篩選:

SELECT query.id, base.id, distance
FROM VECTOR_SEARCH(
  (SELECT * FROM my_dataset.my_table WHERE produced_date = '2025-01-01'),
  'embedding',
  TABLE samples.test,
  distance_type => 'COSINE',
  top_k => 10
);

範例

在以日期時間分區的資料表上建立分區向量索引:

-- Create a datetime-partitioned table.
CREATE TABLE my_dataset.my_table(
  id INT64,
  produced_date DATETIME,
  embeddings ARRAY
)
PARTITION BY produced_date;

-- Create a partitioned vector index on the table.
CREATE VECTOR INDEX index0 ON my_dataset.my_table(embeddings)
PARTITION BY produced_date
OPTIONS(index_type='TREE_AH', distance_type='COSINE');

在以時間戳記分區的資料表上建立分區向量索引:

-- Create a timestamp-partitioned table.
CREATE TABLE my_dataset.my_table(
  id INT64,
  produced_time TIMESTAMP,
  embeddings ARRAY
)
PARTITION BY TIMESTAMP_TRUNC(produced_time, HOUR);

-- Create a partitioned vector index on the table.
CREATE VECTOR INDEX index0 ON my_dataset.my_table(embeddings)
PARTITION BY TIMESTAMP_TRUNC(produced_time, HOUR)
OPTIONS(index_type='TREE_AH', distance_type='COSINE');

在整數範圍分區資料表上建立分區向量索引:

-- Create a integer range-partitioned table.
CREATE TABLE my_dataset.my_table(
  id INT64,
  embeddings ARRAY
)
PARTITION BY RANGE_BUCKET(id, GENERATE_ARRAY(-100, 100, 20));

-- Create a partitioned vector index on the table.
CREATE VECTOR INDEX index0 ON my_dataset.my_table(embeddings)
PARTITION BY RANGE_BUCKET(id, GENERATE_ARRAY(-100, 100, 20))
OPTIONS(index_type='TREE_AH', distance_type='COSINE');

在擷取時間分區資料表上建立分區向量索引:

-- Create a ingestion time-partitioned table.
CREATE TABLE my_dataset.my_table(
  id INT64,
  embeddings ARRAY
)
PARTITION BY TIMESTAMP_TRUNC(_PARTITIONTIME, DAY);

-- Create a partitioned vector index on the table.
CREATE VECTOR INDEX index0 ON my_dataset.my_table(embeddings)
PARTITION BY TIMESTAMP_TRUNC(_PARTITIONTIME, DAY)
OPTIONS(index_type='TREE_AH', distance_type='COSINE');

預先篩選限制

瞭解資料編入索引的時間

向量索引完全由 BigQuery 管理,且會在索引資料表變更時自動重新整理。

建立索引作業為非同步性質。在基礎資料表中新增資料列後,索引會過一段時間才會反映這些變更。不過,VECTOR_SEARCH 函式仍會將所有資料列納入考量,不會遺漏未建立索引的資料列。函式會使用索引搜尋已建立索引的記錄,並對尚未建立索引的記錄使用暴力搜尋法。

如果是在小於 10 MB 的資料表上建立向量索引,系統就不會填入向量索引。同樣地,如果從已建立索引的資料表中刪除資料,且資料表大小低於 10 MB,系統就會暫時停用向量索引。在這種情況下,向量搜尋查詢不會使用索引,且 Job 資源的 vectorSearchStatistics 區段中的 indexUnusedReasons 程式碼為 BASE_TABLE_TOO_SMALL。如果沒有索引,VECTOR_SEARCH 會自動改用暴力搜尋法,尋找最接近的嵌入內容。

如果刪除資料表中的索引資料欄,或重新命名資料表本身,系統會自動刪除向量索引。

監控向量索引的狀態

您可以查詢 INFORMATION_SCHEMA 檢視畫面,監控向量索引的健康狀態。下列檢視區塊包含向量索引的中繼資料:

向量索引範例

以下範例會顯示專案 my_project 中,資料集 my_dataset 內資料表的所有有效向量索引。包括名稱、用於建立這些物件的 DDL 陳述式,以及涵蓋範圍百分比。如果編入索引的基礎資料表小於 10 MB,系統就不會填入索引,此時 coverage_percentage 值為 0。

SELECT table_name, index_name, ddl, coverage_percentage
FROM my_project.my_dataset.INFORMATION_SCHEMA.VECTOR_INDEXES
WHERE index_status = 'ACTIVE';

結果大致如下:

+------------+------------+-------------------------------------------------------------------------------------------------+---------------------+
| table_name | index_name | ddl                                                                                             | coverage_percentage |
+------------+------------+-------------------------------------------------------------------------------------------------+---------------------+
| table1     | indexa     | CREATE VECTOR INDEX `indexa` ON `my_project.my_dataset.table1`(embeddings)                      | 100                 |
|            |            | OPTIONS (distance_type = 'EUCLIDEAN', index_type = 'IVF', ivf_options = '{"num_lists": 100}')   |                     |
+------------+------------+-------------------------------------------------------------------------------------------------+---------------------+
| table2     | indexb     | CREATE VECTOR INDEX `indexb` ON `my_project.my_dataset.table2`(vectors)                         | 42                  |
|            |            | OPTIONS (distance_type = 'COSINE', index_type = 'IVF', ivf_options = '{"num_lists": 500}')      |                     |
+------------+------------+-------------------------------------------------------------------------------------------------+---------------------+
| table3     | indexc     | CREATE VECTOR INDEX `indexc` ON `my_project.my_dataset.table3`(vectors)                         | 98                  |
|            |            | OPTIONS (distance_type = 'DOT_PRODUCT', index_type = 'TREE_AH',                                 |                     |
|            |            |          tree_ah_options = '{"leaf_node_embedding_count": 1000, "normalization_type": "NONE"}') |                     |
+------------+------------+-------------------------------------------------------------------------------------------------+---------------------+

向量索引資料欄範例

下列查詢會擷取具有向量索引的資料欄相關資訊:

SELECT table_name, index_name, index_column_name, index_field_path
FROM my_project.dataset.INFORMATION_SCHEMA.VECTOR_INDEX_COLUMNS;

結果大致如下:

+------------+------------+-------------------+------------------+
| table_name | index_name | index_column_name | index_field_path |
+------------+------------+-------------------+------------------+
| table1     | indexa     | embeddings        | embeddings       |
| table2     | indexb     | vectors           | vectors          |
| table3     | indexc     | vectors           | vectors          |
+------------+------------+-------------------+------------------+

向量索引選項範例

以下查詢會擷取向量索引選項的相關資訊:

SELECT table_name, index_name, option_name, option_type, option_value
FROM my_project.dataset.INFORMATION_SCHEMA.VECTOR_INDEX_OPTIONS;

結果大致如下:

+------------+------------+------------------+------------------+-------------------------------------------------------------------+
| table_name | index_name | option_name      | option_type      | option_value                                                      |
+------------+------------+------------------+------------------+-------------------------------------------------------------------+
| table1     | indexa     | index_type       | STRING           | IVF                                                               |
| table1     | indexa     | distance_type    | STRING           | EUCLIDEAN                                                         |
| table1     | indexa     | ivf_options      | STRING           | {"num_lists": 100}                                                |
| table2     | indexb     | index_type       | STRING           | IVF                                                               |
| table2     | indexb     | distance_type    | STRING           | COSINE                                                            |
| table2     | indexb     | ivf_options      | STRING           | {"num_lists": 500}                                                |
| table3     | indexc     | index_type       | STRING           | TREE_AH                                                           |
| table3     | indexc     | distance_type    | STRING           | DOT_PRODUCT                                                       |
| table3     | indexc     | tree_ah_options  | STRING           | {"leaf_node_embedding_count": 1000, "normalization_type": "NONE"} |
+------------+------------+------------------+------------------+-------------------------------------------------------------------+

驗證向量索引使用情況

如要瞭解向量索引的使用情形,請查看執行向量搜尋查詢的作業中繼資料。您可以使用 Google Cloud 控制台、bq 指令列工具、BigQuery API 或用戶端程式庫,查看工作的中繼資料

使用 Google Cloud 控制台時,您可以在「向量索引使用模式」和「未使用向量索引的原因」欄位中,找到向量索引使用資訊。

使用 bq 工具或 BigQuery API 時,您可以在 Job 資源的 VectorSearchStatistics 區段中,找到向量索引使用資訊。

索引使用模式會提供下列其中一個值,指出是否使用了向量索引:

  • UNUSED:未使用向量索引。
  • PARTIALLY_USED:查詢中的部分 VECTOR_SEARCH 函式使用向量索引,部分則沒有。
  • FULLY_USED:查詢中的每個 VECTOR_SEARCH 函式都使用向量索引。

當索引使用模式值為 UNUSEDPARTIALLY_USED 時,未使用的索引原因會指出查詢中未使用向量索引的原因。

舉例來說,bq show --format=prettyjson -j my_job_id 傳回的下列結果顯示,由於 VECTOR_SEARCH 函式中指定了 use_brute_force 選項,因此系統並未使用索引:

"vectorSearchStatistics": {
  "indexUnusedReasons": [
    {
      "baseTable": {
        "datasetId": "my_dataset",
        "projectId": "my_project",
        "tableId": "my_table"
      },
      "code": "INDEX_SUPPRESSED_BY_FUNCTION_OPTION",
      "message": "No vector index was used for the base table `my_project:my_dataset.my_table` because use_brute_force option has been specified."
    }
  ],
  "indexUsageMode": "UNUSED"
}

索引管理選項

如要建立索引並讓 BigQuery 維護索引,有兩種做法:

使用共用運算單元

如果您尚未將專案設定為使用專屬預留項目進行索引,系統會在免費的共用運算單元集區中處理索引管理作業,但須遵守下列限制。

如果新增至資料表的資料導致已建立索引的資料表總大小超出貴機構的限制,BigQuery 會暫停所有已建立索引的資料表索引管理作業。發生這種情況時,INFORMATION_SCHEMA.VECTOR_INDEXES 檢視區塊中的 index_status 欄位會顯示 PENDING DISABLEMENT,且系統會將索引排入刪除佇列。索引停用期間,系統仍會用於查詢,且您仍須支付索引儲存空間費用。刪除索引後,index_status 欄位會將索引顯示為 TEMPORARILY DISABLED。處於這個狀態時,查詢不會使用索引,您也不會產生索引儲存空間費用。在本例中,IndexUnusedReason 程式碼BASE_TABLE_TOO_LARGE

如果您從資料表刪除資料,且索引資料表的總大小低於機構的限制,系統就會恢復所有索引資料表的索引管理作業。檢視區塊中的 index_status 欄位為 ACTIVE,查詢可以使用索引,且您需要支付索引儲存空間費用。INFORMATION_SCHEMA.VECTOR_INDEXES

您可以透過 INFORMATION_SCHEMA.SEARCH_INDEXES_BY_ORGANIZATION 檢視區塊,瞭解目前在特定區域內,各專案和資料表的用量,以及與機構上限的差距。

BigQuery 不保證共用集區的可用容量或您看到的索引總處理量。對於正式版應用程式,您可能想使用專屬時段處理索引。

使用自己的預留項目

您也可以選擇不使用預設的共用運算單元集區,改用自己的預留項目為資料表建立索引。使用自己的預留空間,可確保索引管理作業 (例如建立、重新整理和背景最佳化) 的效能穩定且可預測。

  • 在預訂中執行索引工作時,資料表大小沒有限制。
  • 使用自己的預留空間,可彈性管理索引。如要建立非常大的索引,或對已建立索引的資料表進行重大更新,可以暫時在指派作業中新增更多運算單元。

如要為專案中具有指定預留項目的資料表建立索引,請在資料表所在的區域建立預留項目。然後,使用 job_type 設為 BACKGROUND 的預訂項目指派專案:

SQL

使用 CREATE ASSIGNMENT DDL 陳述式

  1. 前往 Google Cloud 控制台的「BigQuery」頁面。

    前往 BigQuery

  2. 在查詢編輯器中輸入下列陳述式:

    CREATE ASSIGNMENT
      `ADMIN_PROJECT_ID.region-LOCATION.RESERVATION_NAME.ASSIGNMENT_ID`
    OPTIONS (
      assignee = 'projects/PROJECT_ID',
      job_type = 'BACKGROUND');

    取代下列項目:

    • ADMIN_PROJECT_ID:擁有預留資源的管理專案專案 ID
    • LOCATION:預訂的地點
    • RESERVATION_NAME:預留項目名稱
    • ASSIGNMENT_ID:指派作業的 ID

      ID 必須是專案和位置的專屬 ID,開頭和結尾須為小寫英文字母或數字,且只能包含小寫英文字母、數字和破折號。

    • PROJECT_ID:包含要建立索引的資料表的專案 ID。這項專案已指派給預留項目。

  3. 按一下「執行」

如要進一步瞭解如何執行查詢,請參閱「執行互動式查詢」。

bq

使用 bq mk 指令:

bq mk \
    --project_id=ADMIN_PROJECT_ID \
    --location=LOCATION \
    --reservation_assignment \
    --reservation_id=RESERVATION_NAME \
    --assignee_id=PROJECT_ID \
    --job_type=BACKGROUND \
    --assignee_type=PROJECT

更改下列內容:

  • ADMIN_PROJECT_ID:擁有預留資源的管理專案專案 ID
  • LOCATION:預訂的地點
  • RESERVATION_NAME:預訂名稱
  • PROJECT_ID:要指派給這項預留位置的專案 ID

查看索引工作

每次在單一表格上建立或更新索引時,系統都會建立新的索引工作。如要查看工作相關資訊,請查詢 INFORMATION_SCHEMA.JOBS* 檢視區塊。您可以在查詢的 WHERE 子句中設定 job_type IS NULL AND SEARCH(job_id, '`search_index`'),篩選出建立索引的工作。以下範例會列出專案 my_project 中五個最新的索引工作:

SELECT *
FROM
 region-us.INFORMATION_SCHEMA.JOBS
WHERE
  project_id  = 'my_project'
  AND job_type IS NULL
  AND SEARCH(job_id, '`search_index`')
ORDER BY
 creation_time DESC
LIMIT 5;

選擇預留大小

如要為預留項目選擇適當的運算單元數量,請考量索引管理工作執行時間、使用的運算單元數量,以及一段時間內的用量。在下列情況下,BigQuery 會觸發索引管理作業:

  • 您在資料表上建立索引。
  • 修改索引資料表中的資料。
  • 資料表結構定義變更,影響建立索引的資料欄。
  • 系統會定期最佳化或更新索引資料和中繼資料。

表格的索引管理工作所需運算單元數量取決於下列因素:

  • 資料表大小
  • 資料擷取至資料表的速率
  • 套用至資料表的 DML 陳述式比率
  • 建構及維護索引時可接受的延遲時間
  • 索引的複雜程度,通常取決於資料的屬性,例如重複字詞的數量
監控使用情況和進度

如要評估有效執行索引管理作業所需的運算單元數量,最佳做法是監控運算單元用量,並據此調整預留大小。下列查詢會產生索引管理工作的每日時段用量。只有過去 30 天的資料會納入區域 us-west1

SELECT
  TIMESTAMP_TRUNC(job.creation_time, DAY) AS usage_date,
  -- Aggregate total_slots_ms used for index-management jobs in a day and divide
  -- by the number of milliseconds in a day. This value is most accurate for
  -- days with consistent slot usage.
  SAFE_DIVIDE(SUM(job.total_slot_ms), (1000 * 60 * 60 * 24)) AS average_daily_slot_usage
FROM
  `region-us-west1`.INFORMATION_SCHEMA.JOBS job
WHERE
  project_id = 'my_project'
  AND job_type IS NULL
  AND SEARCH(job_id, '`search_index`')
GROUP BY
  usage_date
ORDER BY
  usage_date DESC
limit 30;

如果執行索引管理工作的時段不足,索引可能會與表格失去同步,索引工作也可能會失敗。在這種情況下,BigQuery 會從頭重建索引。為避免索引不同步,請確保有足夠的時段來支援資料擷取和最佳化作業的索引更新。如要進一步瞭解如何監控時段用量,請參閱管理員資源圖表

刪除向量索引

如果不再需要向量索引,或想變更資料表上建立索引的資料欄,可以使用 DROP VECTOR INDEX DDL 陳述式刪除該資料表的索引。

例如:

DROP VECTOR INDEX my_index ON my_dataset.indexed_table;

如果刪除已建立索引的資料表,系統會自動刪除索引。

後續步驟