Vektorindexe verwalten

Wenn Sie Feedback geben oder Support für dieses Feature anfordern möchten, senden Sie eine E-Mail an bq-vector-search@google.com.

In diesem Dokument wird beschrieben, wie Vektorindexe erstellt und verwaltet werden.

Ein Vektorindex ist eine Datenstruktur, die es der Funktion VECTOR_SEARCH ermöglicht, eine effizientere Vektorsuche von Einbettungen durchzuführen. Wenn VECTOR_SEARCH einen Vektorindex verwenden kann, verwendet die Funktion die Suchmethode Annäherung an den nächsten Nachbarn, um die Suchleistung zu verbessern, mit dem Kompromiss von Recall reduzieren und so ungefähre Ergebnisse liefern.

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 Datenmitbearbeiter (roles/bigquery.dataEditor)

Vektorindex erstellen

Verwenden Sie zum Erstellen eines 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)
    OPTIONS(index_type = INDEX_TYPE,
      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 ist der Name der Tabelle, die die Spalte mit Einbettungsdaten enthält.
    • COLUMN_NAME ist der Name einer Spalte, die die Einbettungsdaten enthält. Die Spalte muss den Typ ARRAY<FLOAT64> haben. Die Spalte darf keine untergeordneten Felder enthalten. Alle Elemente im Array dürfen nicht NULL sein und alle Werte in der Spalte müssen dieselben Arraydimensionen haben.
    • INDEX_TYPE: der Algorithmus, der zum Erstellen des Vektorindex verwendet werden soll. IVF ist der einzige unterstützte Wert. Wenn Sie IVF angeben, wird der Vektorindex als umgekehrter Dateiindex (IVF) erstellt. Dabei wird ein k-Means-Algorithmus eingesetzt, um die Vektordaten in Clustern zu gruppieren und dann die Vektordaten basierend auf diesen Clustern zu partitionieren. Wenn Sie die Funktion VECTOR_SEARCH zum Suchen in den Vektordaten verwenden, kann es diese Partitionen nutzen, um die zu lesende Datenmenge zu reduzieren, um zu bestimmen, ein Ergebnis.
    • DISTANCE_TYPE: Gibt den Standarddistanztyp an, der bei einer Vektorsuche mit diesem Index verwendet werden soll. Die unterstützten Werte sind EUCLIDEAN und COSINE. Standardmäßig ist EUCLIDEAN ausgewählt.

      Bei der Indexerstellung selbst wird immer die EUCLIDEAN-Entfernung für das Training verwendet, die in der Funktion VECTOR_SEARCH verwendete Entfernung kann jedoch abweichen.

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

    • NUM_LISTS: ein INT64-Wert, der kleiner oder gleich 5.000 ist, bestimmt, wie viele Listen der IVF-Algorithmus erstellt. Der IVF-Algorithmus teilt den gesamten Datenbereich in eine Reihe von Listen auf, die NUM_LISTS entsprechen. Datenpunkte, die näher beieinander liegen, werden eher in dieselbe Liste aufgenommen. Wenn NUM_LISTS klein ist, haben Sie weniger Listen mit mehr Datenpunkten. Bei einem größeren Wert werden dagegen mehr Listen mit weniger Datenpunkten erstellt.

      Sie können NUM_LISTS in Kombination mit dem Argument fraction_lists_to_search in der Funktion VECTOR_SEARCH verwenden, um eine effiziente Vektorsuche zu erstellen. Wenn Sie Daten haben, die in vielen kleinen Gruppen im Einbettungsbereich verteilt sind, geben Sie einen hohen Wert für NUM_LISTS an, um einen Index mit mehr Listen zu erstellen, und einen niedrigeren Wert für fraction_lists_to_search, um weniger Listen in der Vektorsuche scannen. Verwenden Sie einen niedrigeren NUM_LISTS und eine höherefraction_lists_to_search wenn die Daten in weniger, größeren Gruppen verteilt sind. Bei Verwendung eines hohen Werts für num_lists kann das Erstellen des Vektorindex länger dauern.

      Wenn Sie NUM_LISTS nicht angeben, berechnet BigQuery einen entsprechenden Wert.

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

Informationen zur Indexaktualisierung

Vektorindexe werden von BigQuery vollständig verwaltet und automatisch aktualisiert, wenn sich die indexierte Tabelle ändert. Wenn Sie die indexierte Spalte in einer Tabelle löschen oder die Tabelle selbst umbenennen, wird der Vektorindex automatisch gelöscht.

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 den indexUnusedReasons-Code im Abschnitt vectorSearchStatistics der Ressource Job ist BASE_TABLE_TOO_SMALL. Ohne den Index greift VECTOR_SEARCH automatisch auf Brute-Force-Angriffe zurück, um die nächsten Nachbarn von Einbettungen zu finden.

Abfragen, die die VECTOR_SEARCH-Funktion verwenden, geben immer korrekte Ergebnisse zurück, auch wenn ein Teil der Daten noch nicht indexiert ist.

Informationen zu Vektorindexen abrufen

Sie können das Vorhandensein und die Bereitschaft eines Vektorindex prüfen, indem Sie INFORMATION_SCHEMA 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 ausgefüllt sein, bevor Sie ihn verwenden können. Anhand der 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 Funktion VECTOR_SEARCH weiterhin für eine Tabelle verwenden. Sie wird ohne den Index möglicherweise nur 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. Sie enthält die Namen, die zum Erstellen verwendeten DDL-Anweisungen und den 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 |
+-------------+-------------+-----------------------------------------------------------------------------------------------+---------------------+
| small_table | myindex1    | CREATE VECTOR INDEX `myindex1` ON `my_project.my_dataset.small_table`(embeddings)             | 100                 |
|             |             | OPTIONS (distance_type = 'EUCLIDEAN', index_type = 'IVF', ivf_options = '{"numLists": 3}')    |                     |
+-------------+-------------+-----------------------------------------------------------------------------------------------+---------------------+
| large_table | myindex2    | CREATE VECTOR INDEX `myindex2` ON `my_project.my_dataset.large_table`(vectors)                |  42                 |
|             |             | OPTIONS (distance_type = 'EUCLIDEAN', index_type = 'IVF', ivf_options = '{"numLists": 12}')   |                     |
+-------------+-------------+-----------------------------------------------------------------------------------------------+---------------------+

Beispiele für Vektorindexspalten

Die folgende Abfrage extrahiert Informationen zu Spalten mit Vektorindexen:

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     | a                 | a                |
| table2     | indexb     | b                 | b                |
| table3     | indexc     | c                 | c                |
+------------+------------+-------------------+------------------+

Beispiele für Optionen für Vektorindexe

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     | distance_type    | STRING           | EUCLIDEAN          |
| table1     | indexa     | index_type       | STRING           | IVF                |
| table2     | indexb     | ivf_options      | STRING           | {"num_lists": 100} |
| table2     | indexb     | index_type       | STRING           | IVF                |
+------------+------------+------------------+------------------+--------------------+

Nutzung des Vektorindex

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 API oder die Clientbibliotheken.

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

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

Der Indexnutzungsmodus gibt an, ob ein Vektorindex verwendet wurde. Geben Sie dazu einen der folgenden Werte an:

  • UNUSED: Es wurde kein Vektorindex verwendet.
  • PARTIALLY_USED: Einige VECTOR_SEARCH-Funktionen in der Abfrage haben Vektorindexe verwendet und andere nicht.
  • FULLY_USED: Jede VECTOR_SEARCH-Funktion in der Abfrage hat einen Vektorindex verwendet.

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

Die folgenden von bq show --format=prettyjson -j my_job_id zurückgegebenen Ergebnisse zeigen beispielsweise, dass der Index nicht verwendet wurde, da 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"
}

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 Tabelle das Limit Ihrer Organisation überschreitet, pausiert BigQuery die Indexverwaltung für alle indexierten Tabellen. 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 ein Index gelöscht wurde, wird im Feld index_status der Index als TEMPORARILY DISABLED angezeigt. In diesem Status wird der Index nicht von Abfragen verwendet und der Indexspeicher wird Ihnen nicht in Rechnung gestellt. 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 für alle indexierten Tabellen 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.

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:

SQL

Verwenden Sie die DDL-Anweisung CREATE ASSIGNMENT.

  1. Öffnen Sie in der Google Cloud Console die Seite BigQuery.

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

Die beste Möglichkeit, die Anzahl der Slots zu beurteilen, die Sie benötigen, um Ihre Indexverwaltungsjobs effizient auszuführen, besteht darin, die Slot-Auslastung zu überwachen und die Reservierungsgröße entsprechend anzupassen. Die folgende Abfrage erzeugt die tägliche Slot-Nutzung für Indexverwaltungsjobs. In der Region us-west1 sind nur die letzten 30 Tage enthalten:

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 Diagramme zu Administratorressourcen.

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

Beispiel:

DROP VECTOR INDEX my_index ON my_dataset.indexed_table;

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

Nächste Schritte