ScaNN-Index erstellen

Gespeicherte Einbettungen verwenden, um ScaNN-Vektorindexe zu generieren und Einbettungen mit AlloyDB for PostgreSQL abzufragen.

Der ScaNN-Index ist ein von Google entwickelter, baumbasierter Quantisierungsindex für die Suche nach dem ungefähren nächsten Nachbarn. Im Vergleich zu HNSW ist die Indexerstellung schneller und der Speicherbedarf geringer. Außerdem bietet es im Vergleich zu HNSW je nach Arbeitslast eine höhere Abfragerate pro Sekunde.

Hinweis

Bevor Sie mit dem Erstellen von Indexen beginnen können, müssen Sie die folgenden Voraussetzungen erfüllen.

  • Einbettungsvektoren wurden einer Tabelle in Ihrer AlloyDB-Datenbank hinzugefügt.

    Wenn Sie versuchen, einen ScaNN-Index für eine leere oder partitionierte Tabelle zu erstellen, können Probleme auftreten. Weitere Informationen zu den generierten Fehlern finden Sie unter Fehlerbehebung bei ScaNN-Indexfehlern. Informationen zum Erstellen eines Index für eine leere oder kleine Tabelle finden Sie unter Verzögerte Indexerstellung für leere oder fast leere Tabellen.

  • Die Erweiterungen vector und alloydb_scann sind installiert:

    CREATE EXTENSION IF NOT EXISTS alloydb_scann CASCADE;
    

    Wenn Sie die alloydb_scann-Erweiterung installieren, wird automatisch geprüft, ob die vector-Erweiterung installiert ist. Falls nicht, wird sie installiert. Sie müssen vector nicht manuell installieren.

  • Wenn Sie einen ScaNN-Index mit vier Ebenen erstellen möchten, müssen Sie zuerst die Vorschaufunktion für Ihre AlloyDB-Instanz aktivieren. Sie haben zwei Möglichkeiten, die Vorschaufunktion zu aktivieren:

Automatisch optimierten Index erstellen

Automatisch optimierte ScaNN-Indizes vereinfachen die Indexerstellung, da AlloyDB die Indexstruktur verwalten und optimieren kann. Wenn Sie eine detaillierte Kontrolle über die Indexoptimierung benötigen, erstellen Sie einen manuell optimierten ScaNN-Index.

Automatisch optimierte Indexe können auf zwei Arten optimiert werden:

  • (Standard) Recall und Latenz der Vektorsuche auf Kosten der Index-Build-Zeit
  • Index-Build-Dauer und Suchleistung in Einklang bringen

Führen Sie den folgenden Befehl aus, um einen automatisch optimierten ScaNN-Index zu erstellen.

CREATE INDEX INDEX_NAME ON TABLE
       USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)

Ersetzen Sie Folgendes:

  • INDEX_NAME: Name des Index, den Sie erstellen möchten. Beispiel: my_scann_index. Indexnamen sind in Ihrer Datenbank freigegeben. Prüfen Sie, ob jeder Indexname für jede Tabelle in Ihrer Datenbank eindeutig ist.

  • TABLE: Die Tabelle, der der Index hinzugefügt werden soll.

  • EMBEDDING_COLUMN: Spalte, in der vector-Daten gespeichert werden.

  • DISTANCE_FUNCTION: Distanzfunktion, die für diesen Index verwendet werden soll. Wählen Sie eine der folgenden Optionen aus:

    • L2-Distanz: l2

    • Skalarprodukt: dot_product

    • Kosinus-Distanz: cosine

Mit diesem Befehl wird ein ScaNN-Index erstellt, der für die Suchleistung optimiert ist und automatische Indexwartung durchführt. Wenn Sie eine dieser Einstellungen ändern möchten, führen Sie den folgenden Befehl aus:

CREATE INDEX INDEX_NAME ON TABLE
       USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
WITH (MODE='AUTO',
      OPTIMIZATION='OPTIMIZATION',
      auto_maintenance='AUTO_MAINTENANCE')

Ersetzen Sie Folgendes:

  • INDEX_NAME: Name des Index, den Sie erstellen möchten. Beispiel: my_scann_index. Indexnamen sind in Ihrer Datenbank freigegeben. Prüfen Sie, ob jeder Indexname für jede Tabelle in Ihrer Datenbank eindeutig ist.

  • TABLE: Die Tabelle, der der Index hinzugefügt werden soll.

  • EMBEDDING_COLUMN: Spalte, in der vector-Daten gespeichert werden.

  • DISTANCE_FUNCTION: Distanzfunktion, die für diesen Index verwendet werden soll. Wählen Sie eine der folgenden Optionen aus:

    • L2-Distanz: l2

    • Skalarprodukt: dot_product

    • Kosinus-Distanz: cosine

  • (Optional) OPTIMIZATION: Legen Sie dafür Folgendes fest:

    • (Standard) SEARCH_OPTIMIZED: Optimiert sowohl die Trefferquote als auch die Latenz der Vektorsuche, was zu längeren Indexerstellungszeiten führt.

    • BALANCED: Die Indexerstellungszeit und die Suchleistung werden in Einklang gebracht.

    Wenn OPTIMIZATION festgelegt ist, muss auch MODE='AUTO' angegeben werden.

  • Optional: AUTO_MAINTENANCE: Steuert, ob die automatische Wartung des Index aktiviert oder deaktiviert ist. Weitere Informationen zur automatischen Wartung finden Sie unter Vektorindexe verwalten.

    • (Standard) ON: AlloyDB führt automatische Wartungsarbeiten am Index durch.

    • OFF: AlloyDB führt keine automatische Wartung des Index durch.

Manuell optimierten Index erstellen

Wenn Ihre Anwendung bestimmte Anforderungen an die Rückruf- und Indexerstellungszeiten hat, können Sie den ScaNN-Index manuell erstellen und optimieren.

Informationen zum manuellen Erstellen eines ScaNN-Index für eine Spalte mit gespeicherten Vektoreinbettungen finden Sie in den folgenden Befehlen.

Zweistufiger Baumindex

CREATE INDEX INDEX_NAME ON TABLE
       USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
WITH (mode='MANUAL',
      num_leaves=NUM_LEAVES_VALUE,
      quantizer=QUANTIZER,
      auto_maintenance=AUTO_MAINTENANCE);
  • INDEX_NAME: Name des Index, den Sie erstellen möchten. Beispiel: my_scann_index. Die Indexnamen sind in Ihrer Datenbank freigegeben. Achten Sie darauf, dass jeder Indexname für jede Tabelle in Ihrer Datenbank eindeutig ist.
  • TABLE: Die Tabelle, der der Index hinzugefügt werden soll.
  • EMBEDDING_COLUMN: Spalte, in der „vector“-Daten gespeichert werden.
  • DISTANCE_FUNCTION: Distanzfunktion, die für diesen Index verwendet werden soll. Wählen Sie eine der folgenden Optionen aus:
    • L2-Distanz: l2
    • Skalarprodukt: dot_product
    • Kosinus-Distanz: cosine
  • NUM_LEAVES_VALUE: Anzahl der Partitionen, die auf diesen Index angewendet werden sollen. Kann auf einen beliebigen Wert zwischen 1 und 30 Millionen festgelegt werden. Weitere Informationen dazu, wie Sie diesen Wert festlegen, finden Sie unter ScaNN-Index abstimmen.
  • QUANTIZER: Der zu verwendende Quantisierungstyp. Der ScaNN-Index kann in die spaltenbasierte Engine geladen werden, um die Vektorsuche weiter zu beschleunigen. Wählen Sie eine der folgenden Optionen aus:
    • (Standard) SQ8: bietet ein ausgewogenes Verhältnis zwischen Abfrageleistung und minimalem Recall-Verlust. Das sind in der Regel weniger als 1–2%.
    • Vorschau AH: Asymmetrisches Hashing (AH) ist im Vergleich zu SQ8 bis zu viermal komprimierter. Wenn die spaltenorientierte Engine aktiviert ist und die Index- und Tabellendaten in die spaltenorientierte Engine eingefügt werden, kann dies die Abfrageleistung potenziell verbessern. Weitere Informationen finden Sie unter Best Practices für die Optimierung von ScaNN.
    • FLAT: Bietet den höchsten Recall (99% oder höher), allerdings auf Kosten der Suchleistung.
  • (Optional) AUTO_MAINTENANCE: Steuert, ob die automatische Wartung des Index aktiviert oder deaktiviert ist. Weitere Informationen zur automatischen Wartung finden Sie unter Vektorindexe verwalten.
    • (Standard) ON: AlloyDB führt automatische Wartungsarbeiten am Index durch.
    • OFF: In AlloyDB wird keine automatische Wartung des Index durchgeführt.

Baumindex mit drei Ebenen

CREATE INDEX INDEX_NAME ON TABLE
       USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
WITH (mode='MANUAL',
      num_leaves=NUM_LEAVES_VALUE,
      quantizer=QUANTIZER,
      auto_maintenance=AUTO_MAINTENANCE,
      max_num_levels = 2);
  • INDEX_NAME: Name des Index, den Sie erstellen möchten. Beispiel: my_scann_index. Die Indexnamen sind in Ihrer Datenbank freigegeben. Achten Sie darauf, dass jeder Indexname für jede Tabelle in Ihrer Datenbank eindeutig ist.
  • TABLE: Die Tabelle, der der Index hinzugefügt werden soll.
  • EMBEDDING_COLUMN: Spalte, in der „vector“-Daten gespeichert werden.
  • DISTANCE_FUNCTION: Distanzfunktion, die für diesen Index verwendet werden soll. Wählen Sie eine der folgenden Optionen aus:
    • L2-Distanz: l2
    • Skalarprodukt: dot_product
    • Kosinus-Distanz: cosine
  • NUM_LEAVES_VALUE: Anzahl der Partitionen, die auf diesen Index angewendet werden sollen. Kann auf einen beliebigen Wert zwischen 1 und 30 Millionen festgelegt werden. Weitere Informationen dazu, wie Sie diesen Wert festlegen, finden Sie unter ScaNN-Index abstimmen.
  • QUANTIZER: Der zu verwendende Quantisierungstyp. Der ScaNN-Index kann in die spaltenbasierte Engine geladen werden, um die Vektorsuche weiter zu beschleunigen. Wählen Sie eine der folgenden Optionen aus:
    • (Standard) SQ8: bietet ein ausgewogenes Verhältnis zwischen Abfrageleistung und minimalem Recall-Verlust. Das sind in der Regel weniger als 1–2%.
    • Vorschau AH: Asymmetrisches Hashing (AH) ist im Vergleich zu SQ8 bis zu viermal komprimierter. Wenn die spaltenorientierte Engine aktiviert ist und die Index- und Tabellendaten in die spaltenorientierte Engine eingefügt werden, kann dies die Abfrageleistung potenziell verbessern. Weitere Informationen finden Sie unter Best Practices für die Optimierung von ScaNN.
    • FLAT: Bietet den höchsten Recall (99% oder höher), allerdings auf Kosten der Suchleistung.
  • (Optional) AUTO_MAINTENANCE: Steuert, ob die automatische Wartung des Index aktiviert oder deaktiviert ist. Weitere Informationen zur automatischen Wartung finden Sie unter Vektorindexe verwalten.
    • (Standard) ON: AlloyDB führt automatische Wartungsarbeiten am Index durch.
    • OFF: In AlloyDB wird keine automatische Wartung des Index durchgeführt.

Baumindex mit vier Ebenen

Baumindexe mit vier Ebenen sind in der Vorschau verfügbar.

CREATE INDEX INDEX_NAME ON TABLE
       USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
WITH (mode='MANUAL',
      num_leaves=NUM_LEAVES_VALUE,
      quantizer=QUANTIZER,
      max_num_levels = 3);
  • INDEX_NAME: Name des Index, den Sie erstellen möchten. Beispiel: my_scann_index. Die Indexnamen sind in Ihrer Datenbank freigegeben. Achten Sie darauf, dass jeder Indexname für jede Tabelle in Ihrer Datenbank eindeutig ist.
  • TABLE: Die Tabelle, der der Index hinzugefügt werden soll.
  • EMBEDDING_COLUMN: Spalte, in der „vector“-Daten gespeichert werden.
  • DISTANCE_FUNCTION: Distanzfunktion, die für diesen Index verwendet werden soll. Wählen Sie eine der folgenden Optionen aus:
    • L2-Distanz: l2
    • Skalarprodukt: dot_product
    • Kosinus-Distanz: cosine
  • NUM_LEAVES_VALUE: Anzahl der Partitionen, die auf diesen Index angewendet werden sollen. Kann auf einen beliebigen Wert zwischen 1 und 30 Millionen festgelegt werden. Weitere Informationen dazu, wie Sie diesen Wert festlegen, finden Sie unter ScaNN-Index abstimmen.
  • QUANTIZER: Der zu verwendende Quantisierungstyp. Der ScaNN-Index kann in die spaltenbasierte Engine geladen werden, um die Vektorsuche weiter zu beschleunigen. Wählen Sie eine der folgenden Optionen aus:
    • (Standard) SQ8: bietet ein ausgewogenes Verhältnis zwischen Abfrageleistung und minimalem Recall-Verlust. Das sind in der Regel weniger als 1–2%.
    • Vorschau AH: Asymmetrisches Hashing (AH) ist im Vergleich zu SQ8 bis zu viermal komprimierter. Wenn die spaltenorientierte Engine aktiviert ist und die Index- und Tabellendaten in die spaltenorientierte Engine eingefügt werden, kann dies die Abfrageleistung potenziell verbessern. Weitere Informationen finden Sie unter Best Practices für die Optimierung von ScaNN.
    • FLAT: Bietet den höchsten Recall (99% oder höher), allerdings auf Kosten der Suchleistung.

Manuell optimierten Index in einen automatisch optimierten Index umwandeln

So wandeln Sie einen manuell optimierten Index in einen automatisch optimierten Index um:

  1. Setzen Sie alle Suchparameter zurück, die für Ihren manuell optimierten Index definiert sind.

    ALTER INDEX INDEX_NAME RESET (PARAMETER_NAME);
    

    Ersetzen Sie die folgenden Variablen:

    • INDEX_NAME: Name des Index, den Sie konvertieren möchten. Beispiel: my_scann_index. Indexnamen sind in Ihrer Datenbank freigegeben. Prüfen Sie, ob jeder Indexname für jede Tabelle in Ihrer Datenbank eindeutig ist.

    • PARAMETER_NAME: Durch Kommas getrennte Liste mit den Namen der Suchparameter, die Sie zurücksetzen möchten. Beispiel: num_leaves, quantization.

      Hinweis: Sie müssen alle anderen Suchparameter zurücksetzen, bevor Sie num_leaves zurücksetzen.

  2. Index neu indexieren, um ihn in einen automatisch optimierten Index zu konvertieren.

    REINDEX INDEX CONCURRENTLY INDEX_NAME;
    

ScaNN-Index für real[]-Datentypen erstellen

Wenn Sie einen Index für eine Einbettungsspalte erstellen möchten, die den Datentyp real[] anstelle von vector verwendet, wandeln Sie die Spalte in den Datentyp vector um:

CREATE INDEX INDEX_NAME ON TABLE
USING scann (CAST(EMBEDDING_COLUMN AS vector(DIMENSIONS)) DISTANCE_FUNCTION)

Ersetzen Sie Folgendes:

  • INDEX_NAME: Name des Index, den Sie erstellen möchten. Beispiel: my_scann_index. Indexnamen sind in Ihrer Datenbank freigegeben. Prüfen Sie, ob jeder Indexname für jede Tabelle in Ihrer Datenbank eindeutig ist.

  • TABLE: Die Tabelle, der der Index hinzugefügt werden soll.

  • DIMENSIONS: Die Anzahl der Dimensionen, die vom Modell unterstützt werden.

  • EMBEDDING_COLUMN: Spalte, in der vector-Daten gespeichert werden.

  • DISTANCE_FUNCTION: Distanzfunktion, die für diesen Index verwendet werden soll. Wählen Sie eine der folgenden Optionen aus:

    • L2-Distanz: l2

    • Skalarprodukt: dot_product

    • Kosinus-Distanz: cosine

Indexierungsfortschritt ansehen

Verwenden Sie zum Anzeigen des Indexierungsfortschritts die pg_stat_progress_create_index-Ansicht:

SELECT * FROM pg_stat_progress_create_index;

In der Spalte phase sehen Sie den aktuellen Status der Indexerstellung. Nach Abschluss der Indexierungsphase ist die Zeile für den Index nicht mehr sichtbar.

Verzögerten Index für leere Tabellen oder Tabellen mit zu wenigen Zeilen erstellen

Standardmäßig können Sie keinen ScaNN-Index für eine Tabelle erstellen, die leer ist oder weniger Zeilen als der Wert der Indexoption num_leaves hat.

Um diese Einschränkung zu umgehen, aktivieren Sie die verzögerte Indexerstellung. Dadurch kann AlloyDB die Indexerstellung verzögern, bis die Anzahl der Zeilen in der Tabelle den von num_leaves definierten Grenzwert erreicht. Sobald der Schwellenwert erreicht ist, startet AlloyDB die Indexerstellung im Hintergrund.

Dieser verzögerte Vorgang ist ein nicht blockierender Prozess, sodass andere Datenbankvorgänge wie Lese- und Schreibvorgänge ohne Unterbrechung fortgesetzt werden können. Da der Index im Hintergrund neu erstellt wird, eignet sich die verzögerte Indexerstellung, wenn Tabellen Datenzeilen in kleinen Batches aufnehmen. Der Index wird automatisch neu erstellt, wenn die Anzahl der Zeilen den Schwellenwert erreicht.

Wenn Sie jedoch planen, in einer einzelnen Transaktion eine große Anzahl von Zeilen in die Tabelle einzufügen, empfehlen wir, die Transaktion in mehrere Transaktionen aufzuteilen oder einen ScaNN-Index zu erstellen, ohne die verzögerte Indexerstellung zu aktivieren.

Verzögerte Indexerstellung aktivieren

So aktivieren Sie die verzögerte Indexerstellung:

  1. Aktivieren Sie das Flag scann.enable_index_maintenance (standardmäßig aktiviert) und das Flag scann.enable_preview_features. Das Flag scann.enable_preview_features aktiviert auch andere Vorschaufunktionen.

    gcloud alloydb instances update INSTANCE_ID \
       --database-flags scann.enable_index_maintenance=on \
       --database-flags scann.enable_preview_features=on \
       --region=REGION_ID \
       --cluster=CLUSTER_ID \
       --project=PROJECT_ID
    

    Ersetzen Sie Folgendes:

    • INSTANCE_ID: Die ID der Instanz.
    • REGION_ID: Die Region, in der sich die Instanz befindet, z. B. us-central1.
    • CLUSTER_ID: Die ID des Clusters, in dem sich die Instanz befindet.
    • PROJECT_ID: Die ID des Projekts, in dem sich der Cluster befindet.
  2. Erstellen Sie einen ScaNN-Index. Wenn Sie einen Index im manuellen Modus erstellen, muss der Parameter auto_maintenance auf on festgelegt sein. Weitere Informationen finden Sie unter Manuell optimierten Index erstellen.

Beschränkungen

  • Der Hintergrundprozess für die automatische Indexerstellung verwendet Flag-Werte auf Datenbankebene. Auch wenn Sie mit dem Befehl SET LOCAL Flags auf Sitzungsebene festlegen, wird der auf Datenbankebene festgelegte Flag-Wert berücksichtigt.
  • Wenn Sie planen, eine große Menge an Daten in einer einzelnen Transaktion in eine leere Tabelle einzufügen, empfehlen wir, die einzelne Einfügetransaktion auszuführen und dann einen ScaNN-Index zu erstellen.

Erzwingen der Indexerstellung für leere oder kleine Tabellen

AlloyDB verwendet Validierungen, um die Erstellung eines ScaNN-Index für eine leere Tabelle oder eine Tabelle mit sehr wenigen Zeilen aus den folgenden Gründen zu verhindern:

  • Der ScaNN-Index wird mit unzureichenden Daten trainiert. Dies kann zu einem schlechten Recall bei Vektorähnlichkeitssuchen führen.

  • Die Schreibvorgänge in die Datenbank können langsamer werden.

Wir empfehlen, die Indexierung zu verschieben, wenn die Leistung nicht optimal ist.

In einigen Entwicklungs- oder Testszenarien müssen Sie jedoch möglicherweise einen Index für eine leere oder kleine Tabelle erstellen. In diesen Fällen können Sie die Indexerstellung erzwingen. Hinweis: Das Erzwingen der Indexerstellung erfordert SUPERUSER-Berechtigungen.

So erzwingen Sie die Indexerstellung:

  1. Legen Sie den Parameter scann.allow_blocked_operations creation auf Sitzungsebene in der Datenbank auf true fest:

    SET scann.allow_blocked_operations = true;
    
  2. Wenn der Nutzer, mit dem Sie diese Abfragen ausführen, keine SUPERUSER-Berechtigungen hat, weisen Sie sie ihm zu:

    CREATE USER USERNAME WITH SUPERUSER PASSWORD PASSWORD;
    

    Ersetzen Sie die folgenden Variablen:

    • USERNAME: Name des Nutzers, dem Sie SUPERUSER-Berechtigungen gewähren möchten.
    • PASSWORD: Das Passwort des Nutzers.

Indexe parallel erstellen

Je nach Dataset und Art des Index, den Sie erstellen möchten, kann AlloyDB automatisch mehrere parallele Worker starten, um den Index schneller zu erstellen. Dies wird häufig ausgelöst, wenn Sie einen ScaNN-Index mit drei oder vier Ebenen erstellen oder Ihr Dataset mehr als 100 Millionen Zeilen umfasst.

Obwohl AlloyDB die Anzahl der parallelen Worker automatisch optimiert, können Sie die parallelen Worker mit den folgenden PostgreSQL-Parametern für die Abfrageplanung anpassen:

Damit beim Erstellen des ScaNN-Index keine Probleme mit dem Arbeitsspeicher auftreten, müssen die Datenbankflags maintenance_work_mem und shared_buffers auf einen Wert festgelegt sein, der kleiner als der gesamte Arbeitsspeicher der Maschine ist.

Abfrage ausführen

Nachdem Sie die Einbettungen in Ihrer Datenbank gespeichert und indexiert haben, können Sie mit dem Abfragen Ihrer Daten beginnen. Mit der alloydb_scann-Erweiterung können keine Bulk-Suchanfragen ausgeführt werden.

Wenn Sie die semantisch nächsten Nachbarn für einen Textstring finden möchten, können Sie die Funktion google_ml.embedding() verwenden, um den Text in einen Vektor zu übersetzen.

Da google_ml.embedding() ein reelles Array zurückgibt, müssen Sie den Funktionsaufruf explizit in vector umwandeln, bevor Sie ihn auf einen der Nearest-Neighbor-Operatoren anwenden, z. B. <-> für die L2-Distanz. Diese Operatoren können dann den ScaNN-Index verwenden, um die Datenbankzeilen mit den semantisch ähnlichsten Einbettungen zu finden.

SELECT * FROM TABLE
ORDER BY EMBEDDING_COLUMN DISTANCE_FUNCTION_QUERY
  google_ml.embedding(
      model_id => 'MODEL_ID',
      content => 'CONTENT')::vector
LIMIT ROW_COUNT

Ersetzen Sie die folgenden Variablen:

  • TABLE: Tabelle, die die Einbettung enthält, mit der der Text verglichen werden soll.

  • EMBEDDING_COLUMN: Spalte mit den gespeicherten Einbettungen.

  • DISTANCE_FUNCTION_QUERY: Distanzfunktion, die für diese Abfrage verwendet werden soll. Wählen Sie das Abfrageäquivalent für die Distanzfunktion aus, die Sie beim Erstellen des Index verwendet haben:

    • L2-Distanz: <->

    • Inneres Produkt: <#>

    • Kosinus-Distanz: <=>

  • MODEL_ID: ID des registrierten Einbettungsmodells, das Sie verwenden möchten.

  • CONTENT: Der Textstring, den Sie in eine Einbettung übersetzen und nach dem Sie suchen möchten.

  • ROW_COUNT: Die Anzahl der zurückzugebenden Zeilen. Geben Sie beispielsweise 1 an, wenn Sie nur das beste Ergebnis erhalten möchten.

Nächste Schritte