Vektorindexe verwalten

In diesem Dokument wird beschrieben, wie Sie Vektorindexe erstellen und verwalten, um Ihre Vektorsuchen zu beschleunigen.

Ein Vektorindex ist eine Datenstruktur, die die effizientere Ausführung der Funktion VECTOR_SEARCH und der Funktion AI.SEARCH ermöglicht, insbesondere bei großen Datasets. Bei Verwendung eines Index nutzen diese Suchfunktionen ANN-Algorithmen (Approximate Nearest Neighbor), um die Abfragelatenz und die Rechenkosten zu reduzieren. ANN führt zwar zu einem gewissen Grad an Näherung, was bedeutet, dass die Trefferquote möglicherweise nicht 100 % beträgt, aber die Leistungsverbesserungen bieten in der Regel einen Vorteil für die meisten Anwendungen.

Rollen und Berechtigungen

Zum Erstellen eines Vektorindex benötigen Sie die IAM-Berechtigung bigquery.tables.createIndex für die Tabelle, in der Sie den Index erstellen. Zum Löschen eines Vektorindex benötigen Sie die Berechtigung bigquery.tables.deleteIndex. Jede der folgenden vordefinierten IAM-Rollen enthält die Berechtigungen, die Sie benötigen, um mit Vektorindexen zu arbeiten:

  • BigQuery Dateninhaber (roles/bigquery.dataOwner)
  • BigQuery-Dateneditor (roles/bigquery.dataEditor)

Vektorindextyp auswählen

BigQuery bietet zwei Vektorindextypen, IVF und TreeAH, die jeweils unterschiedliche Anwendungsfälle unterstützen. BigQuery unterstützt das Batching für die Vektorsuche, indem mehrere Zeilen der Eingabedaten im VECTOR_SEARCH verarbeitet werden. Für kleine Abfrage-Batches werden IVF-Indizes bevorzugt. Für große Abfragebatches werden TreeAH-Indizes bevorzugt, die mit dem ScaNN-Algorithmus von Google erstellt werden.

IVF-Index

IVF ist ein invertierter Dateiindex, der einen k-Means-Algorithmus verwendet, um die Vektordaten zu clustern und dann die Vektordaten basierend auf diesen Clustern zu partitionieren. Die Funktionen VECTOR_SEARCH und AI.SEARCH können diese Partitionen verwenden, um die Datenmenge zu reduzieren, die zum Ermitteln eines Ergebnisses gelesen werden muss.

TreeAH-Index

Der TreeAH-Indextyp ist nach seiner Kombination aus einer baumartigen Struktur und der Verwendung von Asymmetric Hashing (AH) benannt, einer wichtigen Quantisierungstechnik des zugrunde liegenden ScaNN-Algorithmus. So funktioniert ein TreeAH-Index:

  1. Die Basistabelle wird in kleinere, besser verwaltbare Shards unterteilt.
  2. Ein Clustering-Modell wird trainiert. Die Anzahl der Cluster wird aus der Option leaf_node_embedding_count im Argument tree_ah_options der CREATE VECTOR INDEX-Anweisung abgeleitet.
  3. Die Vektoren werden mit Produktquantisierung komprimiert, einer Technik, die die Arbeitsspeichernutzung reduziert. Die komprimierten Vektoren werden dann anstelle der Originalvektoren in den Indextabellen gespeichert, wodurch die Größe des Vektorindex reduziert wird.
  4. Wenn die Funktion VECTOR_SEARCH oder AI.SEARCH ausgeführt wird, wird mithilfe von asymmetrischem Hashing effizient eine Kandidatenliste für jeden Abfragevektor berechnet. Diese Methode ist hardwareoptimiert für ungefähre Distanzberechnungen. Diese Kandidaten werden dann mithilfe von exakten Einbettungen neu bewertet und neu eingestuft.

Der TreeAH-Algorithmus ist für Batchabfragen optimiert, die Hunderte oder mehr Abfragevektoren verarbeiten. Die Verwendung der Produktquantisierung kann die Latenz und die Kosten erheblich reduzieren, möglicherweise um Größenordnungen im Vergleich zu IVF. Aufgrund des erhöhten Overheads ist der IVF-Algorithmus jedoch möglicherweise besser, wenn Sie eine kleinere Anzahl von Abfragevektoren haben.

Wir empfehlen Ihnen, den Index vom Typ „TreeAH“ zu verwenden, wenn Ihr Anwendungsfall die folgenden Kriterien erfüllt:

  • Ihre Tabelle enthält maximal 200 Millionen Zeilen.

  • Sie führen häufig große Batchabfragen mit Hunderten oder mehr Abfragevektoren aus.

Bei Anfragen mit kleinen Batches mit dem Index-Typ „TreeAH“ kann VECTOR_SEARCH oder AI.SEARCH auf die Brute-Force-Suche zurückgreifen. In diesem Fall wird ein IndexUnusedReason angegeben, um zu erklären, warum der Vektorindex nicht verwendet wurde.

IVF-Vektorindex erstellen

Verwenden Sie zum Erstellen eines IVF-Vektorindex die Datendefinitionssprachen-Anweisung (DDL) CREATE VECTOR INDEX:

  1. Rufen Sie die Seite BigQuery auf.

    BigQuery aufrufen

  2. Führen Sie im Abfrageeditor folgende SQL-Anweisung aus:

    So erstellen Sie einen IVF-Vektorindex:

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

    Ersetzen Sie Folgendes:

    • INDEX_NAME: Der Name des Vektorindex, den Sie erstellen. Da der Index immer im selben Projekt und Dataset wie die Basistabelle erstellt wird, müssen Sie Projekt und Dataset nicht im Namen angeben.
    • DATASET_NAME: der Name des Datasets, das die Tabelle enthält.
    • TABLE_NAME: Der Name der Tabelle, die die Spalte mit Einbettungsdaten enthält.
    • COLUMN_NAME: Der Name einer Spalte, die die Einbettungsdaten enthält. Die Spalte muss den Typ ARRAY<FLOAT64> haben oder, wenn Sie die autonome Einbettungsgenerierung verwenden, den Typ STRUCT<result ARRAY<FLOAT64>, status STRING>.

      In allen Fällen dürfen die Elemente im Einbettungsarray nicht NULL sein und alle Werte in der Spalte müssen dieselben Arraydimensionen haben.

      Wenn der Spaltentyp STRUCT<result ARRAY<FLOAT64>, status STRING> ist, kann der STRUCT-Wert NULL sein oder das result-Array kann NULL sein. Alle Zeilen mit NULL für diese Werte werden ignoriert.

    • STORED_COLUMN_NAME: Der Name einer Spalte oberster Ebene in der Tabelle, die im Vektorindex gespeichert werden soll. Der Spaltentyp darf nicht RANGE sein. Gespeicherte Spalten werden nicht verwendet, wenn die Tabelle eine Zugriffsrichtlinie auf Zeilenebene hat oder die Spalte ein Richtlinien-Tag hat. Informationen zum Aktivieren gespeicherter Spalten finden Sie unter Spalten speichern und vorfiltern.

    • DISTANCE_TYPE: Gibt den Standarddistanztyp an, der bei einer Vektorsuche mit diesem Index verwendet werden soll. Die unterstützten Werte sind EUCLIDEAN, COSINE und DOT_PRODUCT. Standardmäßig ist EUCLIDEAN ausgewählt.

      Für die Indexerstellung selbst wird immer die EUCLIDEAN-Distanz für das Training verwendet. Die in Ihrer Suchfunktion verwendete Distanz kann jedoch abweichen.

      Wenn Sie einen Wert für das Argument distance_type der Funktion VECTOR_SEARCH oder AI.SEARCH angeben, wird dieser Wert anstelle des Werts DISTANCE_TYPE verwendet.

    • NUM_LISTS: ein INT64-Wert, der die Anzahl der Listen angibt, in die der IVF-Index Ihre Vektordaten clustert und dann partitioniert. Dieser Wert muss 5.000 oder weniger betragen. Bei der Indexierung werden Vektoren der Liste zugewiesen, die dem Schwerpunkt des nächstgelegenen Clusters entspricht. Wenn Sie dieses Argument weglassen, bestimmt BigQuery einen Standardwert basierend auf Ihren Datenmerkmalen. Der Standardwert ist für die meisten Anwendungsfälle geeignet.

      NUM_LISTS steuert die Granularität der Abfrageoptimierung. Höhere Werte führen zu mehr Listen. Sie können also die Option fraction_lists_to_search Ihrer Suchfunktion so festlegen, dass ein kleinerer Prozentsatz des Index gescannt wird. Beispielsweise 1% von 100 Listen statt 10% von 10 Listen. Dies ermöglicht eine genauere Steuerung der Suchgeschwindigkeit und des Recalls, erhöht jedoch die Indexierungskosten geringfügig. Legen Sie diesen Argumentwert entsprechend der Genauigkeit fest, mit der Sie den Abfragebereich anpassen müssen.

Im folgenden Beispiel wird ein Vektorindex für die Spalte embedding von my_table erstellt:

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

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

Im folgenden Beispiel wird ein Vektorindex für die Spalte embedding von my_table erstellt und der zu verwendende Abstandstyp sowie die IVF-Optionen angegeben:

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

Im folgenden Beispiel wird eine Tabelle mit aktivierter autonomer Einbettungsgenerierung erstellt und ein Vektorindex für die Tabelle erstellt. Die Einbettungsspalte description_embedding wird automatisch anhand der Spalte description generiert.

CREATE TABLE mydataset.products (
  description STRING,
  description_embedding STRUCT<result ARRAY<FLOAT64>, status STRING>
    GENERATED ALWAYS AS (
      AI.EMBED(description, connection_id => 'us.example_connection',
        endpoint => 'text-embedding-005'))
    STORED OPTIONS( asynchronous = TRUE ));

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

TreeAH-Vektorindex erstellen

Verwenden Sie zum Erstellen eines TreeAH-Vektorindex die Datendefinitionssprachen-Anweisung (DDL) CREATE VECTOR INDEX:

  1. Rufen Sie die Seite BigQuery auf.

    BigQuery aufrufen

  2. Führen Sie im Abfrageeditor folgende SQL-Anweisung aus:

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

    Ersetzen Sie Folgendes:

    • INDEX_NAME: der Name des Vektorindex, den Sie erstellen. Da der Index immer im selben Projekt und Dataset wie die Basistabelle erstellt wird, müssen Sie Projekt und Dataset nicht im Namen angeben.
    • DATASET_NAME: der Name des Datasets, das die Tabelle enthält.
    • TABLE_NAME: Der Name der Tabelle, die die Spalte mit Einbettungsdaten enthält.
    • COLUMN_NAME: der Name einer Spalte, die die Einbettungsdaten enthält. Die Spalte muss den Typ ARRAY<FLOAT64> haben oder, wenn Sie die automatische Generierung von Einbettungen verwenden, den Typ STRUCT<result ARRAY<FLOAT64>, status STRING>.

      In allen Fällen dürfen alle Elemente im Einbettungs-Array nicht NULL sein und alle Werte in der Spalte müssen dieselben Array-Dimensionen haben. Die Array-Dimension muss mindestens 2 sein.

      Wenn der Spaltentyp STRUCT<result ARRAY<FLOAT64>, status STRING> ist, kann der STRUCT-Wert NULL sein oder das result-Array kann NULL sein. Alle Zeilen mit NULL für diese Werte werden ignoriert.

    • STORED_COLUMN_NAME: Der Name einer Spalte der obersten Ebene in der Tabelle, die im Vektorindex gespeichert werden soll. Der Spaltentyp darf nicht RANGE sein. Gespeicherte Spalten werden nicht verwendet, wenn die Tabelle eine Zugriffsrichtlinie auf Zeilenebene oder die Spalte ein Richtlinien-Tag hat. Informationen zum Aktivieren gespeicherter Spalten finden Sie unter Spalten speichern und vorfiltern.

    • DISTANCE_TYPE: ein optionales Argument, das den Standarddistanztyp angibt, der bei einer Vektorsuche mit diesem Index verwendet werden soll. Die unterstützten Werte sind EUCLIDEAN, COSINE und DOT_PRODUCT. Standardmäßig ist EUCLIDEAN ausgewählt.

      Für die Indexerstellung selbst wird immer die EUCLIDEAN-Distanz für das Training verwendet. Die in der Suchfunktion verwendete Distanz kann jedoch abweichen.

      Wenn Sie einen Wert für das Argument distance_type der Funktion VECTOR_SEARCH oder AI.SEARCH angeben, wird dieser Wert anstelle des Werts DISTANCE_TYPE verwendet.

    • LEAF_NODE_EMBEDDING_COUNT: ein INT64-Wert größer oder gleich 500, der die ungefähre Anzahl von Vektoren in jedem Blattknoten des Baums angibt, den der TreeAH-Algorithmus erstellt. Der TreeAH-Algorithmus unterteilt den gesamten Datenbereich in eine Reihe von Listen, wobei jede Liste ungefähr LEAF_NODE_EMBEDDING_COUNT Datenpunkte enthält. Bei einem niedrigeren Wert werden mehr Listen mit weniger Datenpunkten erstellt, bei einem höheren Wert weniger Listen mit mehr Datenpunkten. Der Standardwert ist 1.000, was für die meisten Datasets geeignet ist.

    • NORMALIZATION_TYPE: Ein STRING-Wert Folgende Werte werden unterstützt: NONE oder L2. Der Standardwert ist NONE. Die Normalisierung erfolgt vor der Verarbeitung sowohl für die Basistabellendaten als auch für die Abfragedaten. Die Einbettungsspalte COLUMN_NAME in TABLE_NAME wird jedoch nicht geändert. Je nach Dataset, Einbettungsmodell und Distanztyp, der bei der Suche verwendet wird, kann die Normalisierung der Einbettungen die Trefferquote verbessern.

Im folgenden Beispiel wird ein Vektorindex für die Spalte embedding von my_table erstellt und der zu verwendende Abstandstyp sowie die TreeAH-Optionen angegeben:

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"}');

Wenn Sie die Leistung von Hybridsuchabfragen verbessern möchten, können Sie die für die Verarbeitung einer lexikalischen Suche erforderlichen Stichwortinformationen in Ihren Vektorindex aufnehmen. Geben Sie dazu lexical_search_columns in Ihrer CREATE VECTOR INDEX-Anweisung an. Dies ist für jeden vorhandenen Typ von Vektorindex wie IVF oder TreeAH möglich. Die folgende CREATE VECTOR INDEX-Anweisung enthält Keyword-Informationen. In diesem Beispiel werden mit der Option lexical_search_columns alle Spalten aufgelistet, die für den lexikalischen Teil einer hybriden Suchanfrage verwendet werden. Jede Spalte, die der lexical_search_columns-Liste hinzugefügt wird, muss auch als gespeicherte Spalte in der STORING-Klausel hinzugefügt werden:

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

Im folgenden Beispiel für die hybride Suche wird ein Vektorindex für die Einbettungsspalte in my_table erstellt. Die Spalten header, content und footer werden für die lexikalische Suche in hybriden Suchanfragen verwendet:

CREATE VECTOR INDEX `hybrid_index`
ON `my_dataset.my_table`(`embedding`)
    STORING(`header`, `content`, `footer`)
  OPTIONS (
    index_type = 'IVF',
    distance_type = 'EUCLIDEAN',
    lexical_search_columns = ['header', 'content', 'footer']);

Filtern

In den folgenden Abschnitten wird erläutert, wie sich Vor- und Nachfilter auf die Suchergebnisse der Vektorsuche auswirken und wie Sie mithilfe von gespeicherten Spalten und Partitionen im Vektorindex vorfiltern.

Vorfilterung und Nachfilterung

Bei VECTOR_SEARCH- oder AI.SEARCH-Aufrufen in BigQuery dienen sowohl die Vorfilterung als auch die Nachfilterung dazu, die Suchergebnisse zu verfeinern, indem Bedingungen auf Metadatenspalten angewendet werden, die den Vektoreinbettungen zugeordnet sind. Es ist wichtig, die Unterschiede, die Implementierung und die Auswirkungen zu verstehen, um die Abfrageleistung, die Kosten und die Genauigkeit zu optimieren.

Vor- und Nachfilterung sind so definiert:

  • Vorabfilterung:Filterbedingungen werden angewendet, bevor bei der Suche nach dem ungefähren nächsten Nachbarn (Approximate Nearest Neighbor, ANN) Distanzberechnungen für Kandidatenvektoren durchgeführt werden. Dadurch wird die Anzahl der Vektoren, die bei der Suche berücksichtigt werden, eingeschränkt. Vorabfilterung führt daher oft zu schnelleren Abfragezeiten und geringeren Rechenkosten, da bei der ANN-Suche weniger potenzielle Kandidaten ausgewertet werden.
  • Nachfilterung: Filterbedingungen werden angewendet, nachdem die ersten top_k nächsten Nachbarn durch die ANN-Suche identifiziert wurden. Dadurch wird die endgültige Ergebnismenge anhand der angegebenen Kriterien verfeinert.

Die Platzierung der WHERE-Klausel bestimmt, ob ein Filter als Vor- oder Nachfilter fungiert.

Wenn Sie einen Vorfilter erstellen möchten, muss die WHERE-Klausel der Abfrage auf das Basistabellenargument der Suchfunktion angewendet werden. Für die Vorfilterung zum Bereinigen von Daten und Optimieren der Indexsuche muss das Prädikat auf eine gespeicherte Spalte oder eine Partitionierungsspalte angewendet werden. Wenn das Prädikat auf eine andere Spalte angewendet wird, einschließlich einer nicht gespeicherten geclusterten Spalte, fungiert es als Nachfilterung und führt zu einem vollständigen Scan.

Im folgenden Beispiel wird gezeigt, wie ein Vorfilter erstellt wird:

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

SELECT *
FROM
  AI.SEARCH(
    (SELECT * FROM my_dataset.my_table WHERE type = 'animal'),
    'content',
    'dog');

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

Wenn Sie eine Nachfilterung erstellen möchten, muss die WHERE-Klausel der Abfrage außerhalb der VECTOR_SEARCH-Funktion angewendet werden, damit die von der Suche zurückgegebenen Ergebnisse gefiltert werden.

Im folgenden Beispiel wird gezeigt, wie Sie eine Nachfilterung erstellen:

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

Wenn Sie die Nachfilterung verwenden oder wenn die von Ihnen angegebenen Basistabellenfilter auf nicht gespeicherte Spalten verweisen und somit als Nachfilter fungieren, enthält die endgültige Ergebnismenge möglicherweise weniger als top_k Zeilen, möglicherweise sogar null Zeilen, wenn das Prädikat selektiv ist. Wenn Sie nach dem Filtern eine bestimmte Anzahl von Ergebnissen benötigen, sollten Sie einen größeren top_k-Wert angeben oder den fraction_lists_to_search-Wert im Funktionsaufruf erhöhen.

In einigen Fällen, insbesondere wenn der Vorfilter sehr selektiv ist, kann die Vorfilterung auch die Größe der Ergebnismenge verringern. Erhöhen Sie in diesem Fall den Wert fraction_lists_to_search im Aufruf der Suchfunktion.

Vorabfilterung mit gespeicherten Spalten

Um die Effizienz Ihres Vektorindex weiter zu verbessern, können Sie Spalten aus Ihrer Basistabelle angeben, die im Vektorindex gespeichert werden sollen. Durch die Verwendung gespeicherter Spalten können Abfragen, die die Funktionen VECTOR_SEARCH oder AI.SEARCH aufrufen, folgendermaßen optimiert werden:

  • Anstatt in einer ganzen Tabelle zu suchen, können Sie eine Suchfunktion in einer Abfrageanweisung aufrufen, die die Basistabelle mit einer WHERE-Klausel vorfiltert. Wenn Ihre Tabelle einen Index hat und Sie nur nach gespeicherten Spalten filtern, optimiert BigQuery die Abfrage, indem die Daten vor der Suche gefiltert und dann der Index verwendet wird, um das kleinere Ergebnis-Set zu durchsuchen. Wenn Sie nach Spalten filtern, die nicht gespeichert sind, wendet BigQuery den Filter nach der Suche in der Tabelle an oder filtert nachträglich.

  • Die Funktionen VECTOR_SEARCH und AI.SEARCH geben eine Struktur namens base aus, die alle Spalten aus der Basistabelle enthält. Ohne gespeicherte Spalten ist ein potenziell teurer Join erforderlich, um die in base gespeicherten Spalten abzurufen. Wenn Sie einen IVF-Index verwenden und Ihre Abfrage nur gespeicherte Spalten aus base auswählt, optimiert BigQuery Ihre Abfrage, um diesen Join zu eliminieren. Bei TreeAH-Indexen wird die Verknüpfung mit der Basistabelle nicht entfernt. Gespeicherte Spalten in TreeAH-Indizes werden nur für die Vorfilterung verwendet.

Wenn Sie Spalten speichern möchten, listen Sie sie in der STORING-Klausel der CREATE VECTOR INDEX-Anweisung auf. Das Speichern von Spalten erhöht die Größe des Vektorindex. Daher sollten Sie nur die am häufigsten verwendeten oder gefilterten Spalten speichern.

Im folgenden Beispiel wird ein Vektorindex mit gespeicherten Spalten erstellt und dann eine Vektorsuchanfrage ausgeführt, bei der nur gespeicherte Spalten ausgewählt werden:

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

Einschränkungen bei gespeicherten Spalten

  • Wenn der Modus, der Typ oder das Schema einer Spalte in der Basistabelle geändert wird und es sich um eine gespeicherte Spalte im Vektorindex handelt, kann es zu einer Verzögerung kommen, bis diese Änderung im Vektorindex übernommen wird. Bis die Aktualisierungen auf den Index angewendet wurden, werden für die Vektorsuchanfragen die geänderten gespeicherten Spalten aus der Basistabelle verwendet.
  • Wenn Sie eine Spalte vom Typ STRUCT aus der query-Ausgabe einer Suchanfrage für eine Tabelle auswählen, die einen Index mit gespeicherten Spalten hat, schlägt die gesamte Abfrage möglicherweise fehl.

Vorfilterung mit Partitionen

Wenn die Tabelle, für die Sie den Vektorindex erstellen, partitioniert ist, können Sie den Vektorindex ebenfalls partitionieren. Die Partitionierung des Vektorindex bietet folgende Vorteile:

  • Die Partitionsbereinigung wird zusätzlich zu den Tabellenpartitionen auf die Vektorindexe angewendet. Die Partitionsbereinigung erfolgt, wenn die Vektorsuche einen qualifizierenden Filter für den Wert der Partitionierungsspalte verwendet. So kann BigQuery die Partitionen scannen, die dem Filter entsprechen, und die verbleibenden Partitionen überspringen. Durch das Pruning von Partitionen können die E/A-Kosten gesenkt werden. Weitere Informationen zum Bereinigen von Partitionen finden Sie unter Partitionierte Tabellen abfragen.
  • Bei der Vektorsuche werden weniger Ergebnisse übersehen, wenn Sie nach der Partitionierungsspalte vorfiltern.

Sie können nur TreeAH-Vektorindexe partitionieren. Sie können keinen partitionierten Vektorindex für eine automatisch generierte Einbettungsspalte erstellen.

Die Partitionierung eines Vektorindex wird nur empfohlen, wenn Sie die meisten Vektorsuchen mithilfe von Vorfiltern auf wenige Partitionen beschränken.

Verwenden Sie zum Erstellen eines partitionierten Index die PARTITION BY-Klausel der CREATE VECTOR INDEX-Anweisung. Die PARTITION BY-Klausel, die Sie in der CREATE VECTOR INDEX-Anweisung angeben, muss mit der PARTITION BY-Klausel übereinstimmen, die in der CREATE TABLE-Anweisung der Tabelle angegeben ist, für die Sie den Vektorindex erstellen. Beispiel:

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

Wenn die Tabelle nach Ganzzahlbereich oder Zeiteinheitsspalte partitioniert ist, wird die Partitionierungsspalte im Vektorindex gespeichert, was die Speicherkosten erhöht. Wenn eine Tabellenspalte sowohl in der STORING- als auch in der PARTITION BY-Klausel der CREATE VECTOR INDEX-Anweisung verwendet wird, wird die Spalte nur einmal gespeichert.

Wenn Sie die Vektorindexpartition verwenden möchten, filtern Sie in der Unterabfrage der Basistabelle des VECTOR_SEARCH- oder AI.SEARCH-Aufrufs nach der Partitionierungsspalte. Im folgenden Beispiel ist die Tabelle samples.items nach der Spalte produced_date partitioniert. Die Unterabfrage der Basistabelle in der VECTOR_SEARCH-Anweisung wird also nach der Spalte produced_date gefiltert:

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

Beispiele

Partitionierten Vektorindex für eine nach Datum/Uhrzeit partitionierte Tabelle erstellen:

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

Partitionierten Vektorindex für eine nach Zeitstempel partitionierte Tabelle erstellen:

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

Partitionierten Vektorindex für eine nach Ganzzahlbereich partitionierte Tabelle erstellen:

-- Create an 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');

Partitionierten Vektorindex für eine nach Aufnahmezeit partitionierte Tabelle erstellen:

-- Create an 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');

Einschränkungen beim Vorfiltern

Wann werden Daten indexiert?

Vektorindexe werden vollständig von BigQuery verwaltet und automatisch aktualisiert, wenn sich die indexierte Tabelle ändert.

Die Indexierung erfolgt asynchron. Zwischen dem Hinzufügen neuer Zeilen zur Basistabelle und dem Zeitpunkt, zu dem die neuen Zeilen im Index berücksichtigt werden, gibt es eine Verzögerung. Die Funktionen VECTOR_SEARCH und AI.SEARCH berücksichtigen jedoch weiterhin alle Zeilen und lassen keine nicht indexierten Zeilen aus. Die Funktionen suchen mithilfe des Index nach indexierten Datensätzen und verwenden die Brute-Force-Suche für die Datensätze, die noch nicht indexiert sind.

Wenn Sie einen Vektorindex für eine automatisch generierte Spalte mit Einbettungen erstellen, beginnt das Training des Index, sobald für mindestens 80% der Zeilen Einbettungen generiert wurden.

Wenn Sie einen Vektorindex für eine Tabelle erstellen, die kleiner als 10 MB ist, wird der Vektorindex nicht ausgefüllt. Dies gilt auch umgekehrt: Wenn Sie Daten aus einer indexierten Tabelle löschen und die Tabellengröße unter 10 MB liegt, wird der Vektorindex vorübergehend deaktiviert. In diesem Fall verwenden Vektorsuchanfragen nicht den Index und der indexUnusedReasons-Code im Abschnitt vectorSearchStatistics der Ressource Job ist BASE_TABLE_TOO_SMALL. Ohne den Index greift Ihre Suchfunktion automatisch auf Brute-Force-Angriffe zurück, um die nächsten Nachbarn von Einbettungen zu finden.

Wenn Sie die indexierte Spalte in einer Tabelle löschen oder die Tabelle selbst umbenennen, wird der Vektorindex automatisch gelöscht.

Status von Vektorindexen überwachen

Sie können den Zustand Ihrer Vektorindexe überwachen, indem Sie INFORMATION_SCHEMA-Ansichten abfragen. Die folgenden Ansichten enthalten Metadaten zu Vektorindexen:

  • Die Ansicht INFORMATION_SCHEMA.VECTOR_INDEXES enthält Informationen zu den Vektorindexen in einem Dataset.

    Nachdem die CREATE VECTOR INDEX-Anweisung abgeschlossen ist, muss der Index noch gefüllt werden, bevor Sie ihn verwenden können. Mit den Spalten last_refresh_time und coverage_percentage können Sie die Bereitschaft eines Vektorindex prüfen. Wenn der Vektorindex nicht bereit ist, können Sie die Funktionen VECTOR_SEARCH und AI.SEARCH trotzdem für eine Tabelle verwenden. Ohne den Index werden sie jedoch möglicherweise langsamer ausgeführt.

  • Die Ansicht INFORMATION_SCHEMA.VECTOR_INDEX_COLUMNS enthält Informationen zu den vektorindexierten Spalten für alle Tabellen in einem Dataset.

  • Die Ansicht INFORMATION_SCHEMA.VECTOR_INDEX_OPTIONS enthält Informationen zu den Optionen, die von den Vektorindexen in einem Dataset verwendet werden.

Beispiele für Vektorindexe

Das folgende Beispiel zeigt alle aktiven Vektorindexe für Tabellen im Dataset my_dataset, das sich im Projekt my_project befindet. Darin enthalten sind die Namen, die zum Erstellen der Indexe verwendeten DDL-Anweisungen und der Deckungsprozentsatz. Ist eine indexierte Basistabelle kleiner als 10 MB, wird der Index nicht ausgefüllt. In diesem Fall ist der Wert coverage_percentage 0.

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

Das Ergebnis sieht etwa so aus:

+------------+------------+-------------------------------------------------------------------------------------------------+---------------------+
| 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"}') |                     |
+------------+------------+-------------------------------------------------------------------------------------------------+---------------------+

Beispiele für Vektorindexspalten

Mit der folgenden Abfrage werden Informationen zu Spalten mit Vektorindexen extrahiert:

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

Das Ergebnis sieht etwa so aus:

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

Beispiele für Vektorindexoptionen

Die folgende Abfrage extrahiert Informationen zu Vektorindexoptionen:

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

Das Ergebnis sieht etwa so aus:

+------------+------------+------------------+------------------+-------------------------------------------------------------------+
| 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"} |
+------------+------------+------------------+------------------+-------------------------------------------------------------------+

Verwendung des Vektorindex prüfen

Informationen zur Verwendung des Vektorindex finden Sie in den Jobmetadaten des Jobs, der die Vektorsuchabfrage ausgeführt hat. Sie können Jobmetadaten aufrufen über die Google Cloud Console, das bq-Befehlszeilentool, die BigQuery API oder die Clientbibliotheken.

Wenn Sie die Google Cloud Console verwenden, finden Sie Informationen zur Nutzung des Vektorindex in den Feldern Nutzungsmodus für Vektorindex und Gründe für nicht verwendeten Vektorindex.

Wenn Sie das bq-Tool oder die BigQuery API verwenden, finden Sie Informationen zur Nutzung von Vektorindexen im Abschnitt VectorSearchStatistics der Ressource Job.

Der Nutzungsmodus für den Index gibt an, ob ein Vektorindex verwendet wurde. Dazu wird einer der folgenden Werte angegeben:

  • UNUSED: Es wurde kein Vektorindex verwendet.
  • PARTIALLY_USED: Einige Suchfunktionen in der Abfrage haben Vektorindexe verwendet, andere nicht.
  • FULLY_USED: Jede Suchfunktion in der Abfrage hat einen Vektorindex verwendet.

Wenn der Wert für den Indexnutzungsmodus UNUSED oder PARTIALLY_USED ist, geben die Gründe für nicht verwendete Indexe an, warum Vektorindexe nicht in der Abfrage verwendet wurden.

Die folgenden Ergebnisse, die von bq show --format=prettyjson -j my_job_id zurückgegeben werden, zeigen beispielsweise, dass der Index nicht verwendet wurde, weil die Option use_brute_force in der Funktion VECTOR_SEARCH angegeben wurde:

"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"
}

Bekanntes Problem: Die Nutzung des Vektorindex ist möglicherweise ungenau, wenn die Abfrage ausgeführt, abgebrochen oder fehlgeschlagen ist.

Optionen für die Indexverwaltung

Sie haben zwei Möglichkeiten, Indexe zu erstellen und von BigQuery verwalten zu lassen:

  • Standardmäßigen freigegebenen Slot-Pool verwenden: Wenn die zu indexierenden Daten unter dem Limit pro Organisation liegen, können Sie den kostenlosen freigegebenen Slot-Pool für die Indexverwaltung verwenden.
  • Eigene Reservierung verwenden: Um einen vorhersehbaren und konsistenten Fortschritt bei der Indexierung für Ihre größeren Produktionsarbeitslasten zu erreichen, können Sie Ihre eigenen Reservierungen für die Indexverwaltung verwenden.

Freigegebene Slots verwenden

Wenn Sie Ihr Projekt nicht für die Verwendung einer dedizierten Reservierung für die Indexierung konfiguriert haben, wird die Indexverwaltung im kostenlosen, freigegebenen Slot-Pool durchgeführt, wobei die folgenden Einschränkungen gelten.

Wenn Sie einer Tabelle Daten hinzufügen, wodurch die Gesamtgröße der indexierten Tabellen das Limit Ihrer Organisation überschreitet, pausiert BigQuery die Indexverwaltung für diese Tabelle. In diesem Fall wird im Feld index_status in der Ansicht INFORMATION_SCHEMA.VECTOR_INDEXES PENDING DISABLEMENT angezeigt und der Index wird zum Löschen in die Warteschlange gestellt. Solange die Deaktivierung des Index aussteht, wird er noch in Anfragen verwendet und Indexspeicher wird Ihnen weiterhin in Rechnung gestellt. Nachdem der Index gelöscht wurde, wird er im Feld index_status als TEMPORARILY DISABLED angezeigt. In diesem Zustand wird der Index nicht in Abfragen verwendet und Ihnen werden keine Kosten für den Indexspeicher berechnet. In diesem Fall lautet der IndexUnusedReason-Code BASE_TABLE_TOO_LARGE.

Wenn Sie Daten aus der Tabelle löschen und die Gesamtgröße der indexierten Tabelle unter das Limit pro Organisation fällt, wird die Indexverwaltung fortgesetzt. Das Feld index_status in der Ansicht INFORMATION_SCHEMA.VECTOR_INDEXES ist ACTIVE. Anfragen können den Index verwenden und Ihnen wird der Indexspeicher in Rechnung gestellt.

Mit der Ansicht INFORMATION_SCHEMA.SEARCH_INDEXES_BY_ORGANIZATION können Sie Ihren aktuellen Verbrauch im Hinblick auf das Limit pro Organisation in einer bestimmten Region nachvollziehen, aufgeschlüsselt nach Projekten und Tabellen.

BigQuery gibt keine Garantien für die verfügbaren Kapazitäten des gemeinsamen Pools oder den angezeigten Durchsatz der Indexierung. Für Produktionsanwendungen kann die Verwendung dedizierter Slots für die Indexverarbeitung sinnvoll sein.

Eigene Reservierung verwenden

Anstatt den standardmäßigen freigegebenen Slot-Pool zu verwenden, können Sie optional eine eigene Reservierung festlegen, um Ihre Tabellen zu indexieren. Die Verwendung Ihrer eigenen Reservierung sorgt für eine vorhersagbare und konsistente Leistung von Indexverwaltungsjobs, z. B. Erstellungs-, Aktualisierungs- und Hintergrundoptimierungen.

  • Wenn ein Indexjob in Ihrer Reservierung ausgeführt wird, gibt es keine Größenbeschränkungen für Tabellen.
  • Mit der eigenen Reservierung können Sie Ihre Indexverwaltung flexibel verwalten. Wenn Sie einen sehr großen Index erstellen oder eine wichtige Aktualisierung einer indexierten Tabelle vornehmen müssen, können Sie der Zuweisung vorübergehend weitere Slots hinzufügen.

Um die Tabelle in einem Projekt mit einer bestimmten Reservierung zu indexieren, erstellen Sie eine Reservierung in der Region, in der sich Ihre Tabellen befinden. Weisen Sie der Reservierung dann das Projekt zu, wobei job_type auf BACKGROUND gesetzt ist. Dadurch werden Ressourcen für Hintergrundoptimierungsjobs freigegeben:

SQL

Verwenden Sie die DDL-Anweisung CREATE ASSIGNMENT.

  1. Rufen Sie in der Google Cloud Console die Seite BigQuery auf.

    BigQuery aufrufen

  2. Geben Sie im Abfrageeditor die folgende Anweisung ein:

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

    Ersetzen Sie Folgendes:

    • ADMIN_PROJECT_ID: die Projekt-ID des Administrationsprojekts, dem die Reservierungsressource gehört
    • LOCATION: der Standort der Reservierung
    • RESERVATION_NAME: der Name der Reservierung
    • ASSIGNMENT_ID: die ID der Zuweisung

      Die ID muss für das Projekt und den Standort eindeutig sein, mit einem Kleinbuchstaben oder einer Zahl beginnen und enden und darf nur Kleinbuchstaben, Zahlen und Bindestriche enthalten.

    • PROJECT_ID: die ID des Projekts, das die zu indexierenden Tabellen enthält. Dieses Projekt wird der Reservierung zugewiesen.

  3. Klicken Sie auf Ausführen.

Informationen zum Ausführen von Abfragen finden Sie unter Interaktive Abfrage ausführen.

bq

Führen Sie den Befehl bq mk aus:

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

Ersetzen Sie Folgendes:

  • ADMIN_PROJECT_ID: die Projekt-ID des Administrationsprojekts, dem die Reservierungsressource gehört
  • LOCATION: der Standort der Reservierung
  • RESERVATION_NAME: der Name der Reservierung
  • PROJECT_ID: die ID des Projekts, das der Reservierung zugewiesen werden soll

Indexierungsjobs ansehen

Bei jeder Erstellung oder Aktualisierung eines Index für eine einzelne Tabelle wird ein neuer Indexierungsjob erstellt. Fragen Sie die Ansichten INFORMATION_SCHEMA.JOBS* ab, um Informationen zum Job anzuzeigen. Sie können nach Indexierungsjobs filtern, indem Sie job_type IS NULL AND SEARCH(job_id, '`search_index`') in der WHERE-Klausel Ihrer Abfrage festlegen. Im folgenden Beispiel werden die fünf neuesten Indexierungsjobs im Projekt my_project aufgelistet:

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;

Reservierungsgröße auswählen

Wenn Sie die richtige Anzahl von Slots für Ihre Reservierung auswählen möchten, sollten Sie berücksichtigen, wann Jobs mit Indexverwaltung ausgeführt werden, wie viele Slots sie verwenden und wie Ihre Nutzung im Laufe der Zeit aussieht. BigQuery löst in den folgenden Situationen einen Indexverwaltungsjob aus:

  • Sie erstellen einen Index für eine Tabelle.
  • Daten werden in einer indexierten Tabelle geändert.
  • Das Schema einer Tabelle ändert sich, was sich darauf auswirkt, welche Spalten indexiert werden.
  • Indexdaten und Metadaten werden regelmäßig optimiert oder aktualisiert.

Die Anzahl der Slots, die Sie für einen Indexverwaltungsjob in einer Tabelle benötigen, hängt von den folgenden Faktoren ab:

  • Die Größe der Tabelle
  • Die Rate der Datenaufnahme in die Tabelle
  • Die Rate der DML-Anweisungen, die auf die Tabelle angewendet werden
  • Die akzeptable Verzögerung zum Erstellen und Verwalten des Index
  • Die Komplexität des Index; normalerweise bestimmt durch Attribute der Daten, z. B. die Anzahl doppelter Begriffe
Nutzung und Fortschritt im Blick behalten

Die beste Möglichkeit, die Anzahl der Slots zu ermitteln, die Sie für die effiziente Ausführung Ihrer Indexverwaltungsjobs benötigen, besteht darin, die Slot-Auslastung zu überwachen und die Reservierungsgröße entsprechend anzupassen. Die folgende Abfrage liefert die tägliche Slot-Nutzung für Indexverwaltungsjobs. In der Region us-west1 werden nur die letzten 30 Tage berücksichtigt:

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;

Wenn nicht genügend Slots zum Ausführen von Indexverwaltungsjobs vorhanden sind, ist der Index möglicherweise nicht mehr mit seiner Tabelle synchron und Indexierungsjobs können fehlschlagen. In diesem Fall erstellt BigQuery den Index von Grund auf neu. Achten Sie darauf, dass genügend Slots vorhanden sind, um Indexaktualisierungen aus der Datenaufnahme und -optimierung zu unterstützen, damit kein nicht synchronisierter Index. Weitere Informationen zum Monitoring der Slot-Nutzung finden Sie unter Ressourcendiagramme für Administratoren.

Vektorindex neu erstellen

Wenn sich Tabellendaten nach der Erstellung eines Vektorindex erheblich ändern, kann der Vektorindex weniger effizient werden. Wenn ein Vektorindex weniger effizient ist, hat eine Vektorsuchanfrage, die bei Verwendung des Index anfangs einen hohen Recall hatte, einen niedrigeren Recall, da die Verschiebung der Datenverteilung in der Basistabelle nicht im Vektorindex dargestellt wird.

Wenn Sie den Recall verbessern möchten, ohne die Latenz von Suchanfragen zu erhöhen, erstellen Sie den Vektorindex neu. Alternativ können Sie den Wert der Option fraction_lists_to_search der Vektorsuche erhöhen, um den Recall zu verbessern. Dadurch wird die Suchanfrage jedoch in der Regel langsamer. Führen Sie die folgende Abfrage aus, um herauszufinden, wann ein Index zuletzt erstellt wurde:

SELECT last_model_build_time
FROM DATASET_NAME.INFORMATION_SCHEMA.VECTOR_INDEXES
WHERE table_name = TABLE_NAME;

Mit der Funktion VECTOR_INDEX.STATISTICS können Sie berechnen, wie stark die Daten einer indexierten Tabelle zwischen dem Zeitpunkt der Erstellung eines Vektorindex und dem aktuellen Zeitpunkt abgewichen sind.

Wenn sich die Tabellendaten so stark geändert haben, dass ein Neuaufbau des Vektorindex erforderlich ist, können Sie den Vektorindex mit der Anweisung ALTER VECTOR INDEX REBUILD neu aufbauen, ohne den Vektorindex zu löschen und ohne Ausfallzeiten des Index. Wenn Sie die Anweisung ausführen, erstellt BigQuery einen Schattenindex, einen Index, der nur im Hintergrund ausgeführt wird und die Konfiguration des aktuellen Index für die Tabelle übernimmt. Der Index wird im Hintergrund trainiert. BigQuery stuft den Schattenindex zum aktiven Index hoch, wenn der Schattenindex eine ausreichende Abdeckung hat.

So erstellen Sie einen Vektorindex neu:

  1. Rufen Sie die Seite BigQuery auf.

    BigQuery aufrufen

  2. Führen Sie im Abfrageeditor die folgende SQL-Anweisung aus, um die Datendrift der indexierten Tabelle zu prüfen:

    SELECT * FROM VECTOR_INDEX.STATISTICS(TABLE DATASET_NAME.TABLE_NAME);

    Ersetzen Sie Folgendes:

    • DATASET_NAME: der Name des Datasets, das die indexierte Tabelle enthält.
    • TABLE_NAME: der Name der Tabelle, die den Vektorindex enthält.

    Die Funktion gibt einen FLOAT64-Wert im Bereich [0,1) zurück. Ein niedrigerer Wert weist auf weniger Drift hin. In der Regel wird ein Wert von 0.3 oder höher als ausreichend signifikante Änderung angesehen, um darauf hinzuweisen, dass eine Neuerstellung des Vektorindex von Vorteil sein könnte.

  3. Wenn die Funktion VECTOR_INDEX.STATISTICS angibt, dass die Tabellendaten erheblich abweichen, führen Sie die folgende SQL-Anweisung aus, um den Vektorindex neu zu erstellen:

    ALTER VECTOR INDEX IF EXISTS INDEX_NAME
    ON DATASET_NAME.TABLE_NAME
    REBUILD;

    Ersetzen Sie Folgendes:

    • INDEX_NAME: Der Name des Vektorindex, den Sie neu erstellen.
    • DATASET_NAME: der Name des Datasets, das die indexierte Tabelle enthält.
    • TABLE_NAME: der Name der Tabelle, die den Vektorindex enthält.

Neuerstellung überwachen

Fragen Sie die Ansicht INFORMATION_SCHEMA.VECTOR_INDEXES ab, um die Neuerstellung des Index zu überwachen. Die folgende Abfrage zeigt beispielsweise den Neuerstellungsstatus aller Indexe für Tabellen im Dataset my_dataset im Projekt my_project. Wenn für einen Index keine Neuerstellung läuft, lautet der Wert für last_index_alteration_info NULL.

SELECT
  table_name,
  index_name,
  last_index_alteration_info.status AS status,
  last_index_alteration_info.new_coverage_percentage AS coverage
FROM my_project.my_dataset.INFORMATION_SCHEMA.VECTOR_INDEXES

Das Ergebnis sieht in etwa so aus:

+------------+------------+-------------+----------+
| table_name | index_name | status      | coverage |
+------------+------------+-------------+----------+
| table1     | index_a    | IN_PROGRESS | 50       |
| table2     | index_b    | null        | null     |
+------------+------------+-------------+----------+

Neuaufbau abbrechen

Verwenden Sie die Systemprozedur BQ.CANCEL_INDEX_ALTERATION, um den Neuaufbau eines Vektorindex abzubrechen. Ein Indexänderungsvorgang kann abgeschlossen werden, bevor die Abbruchanfrage verarbeitet wird. Fragen Sie die Ansicht INFORMATION_SCHEMA.VECTOR_INDEXES ab, um zu prüfen, ob der Vorgang erfolgreich abgebrochen wurde. Wenn der Abbruch erfolgreich war, wird das Feld last_model_build_time nicht aktualisiert und das Feld last_index_alteration_info ist für diesen Index nicht vorhanden.

Vektorindex löschen

Wenn Sie einen Vektorindex nicht mehr benötigen oder die in einer Tabelle indexierte Spalte ändern möchten, können Sie den Index für diese Tabelle mit der DDL-Anweisung DROP VECTOR INDEX löschen:

  1. Rufen Sie die Seite BigQuery auf.

    BigQuery aufrufen

  2. Führen Sie im Abfrageeditor folgende SQL-Anweisung aus:

    DROP VECTOR INDEX INDEX_NAME ON DATASET_NAME.TABLE_NAME;

    Ersetzen Sie Folgendes:

    • INDEX_NAME: Der Name des Vektorindex, den Sie löschen.
    • DATASET_NAME: der Name des Datasets, das die indexierte Tabelle enthält.
    • TABLE_NAME: der Name der Tabelle, die den Vektorindex enthält.

Wenn eine indexierte Tabelle gelöscht wird, wird ihr Index automatisch gelöscht.

Um Onlineanwendungen mit extrem niedriger Latenz zu ermöglichen, können Sie die BigQuery -Integration mit der Gemini Enterprise Agent Platform Vektorsuche verwenden, um Ihre BigQuery-Einbettungen in Vektorsuche zu importieren und Endpunkte mit niedriger Latenz bereitzustellen. Weitere Informationen finden Sie unter Indexdaten aus BigQuery importieren.

Nächste Schritte