Aktivieren und Verwenden der DiskANN-Erweiterung in Azure Database for PostgreSQL – Flexible Server

DiskANN ist ein skalierbarer Algorithmus für angenäherte nächste Nachbarnsuche zur effizienten Vektorsuche in jeder Größenordnung. Diese Funktion bietet hohen Recall, viele Abfragen pro Sekunde und eine niedrige Abfragelatenz, auch für Datasets mit Milliarden Elementen. Diese Merkmale machen es zu einem leistungsstarken Tool für die Verarbeitung großer Datenmengen.

Weitere Informationen zu DiskANN finden Sie unter DiskANN: Vektorsuche für Webskalensuche und Empfehlung.

Die pg_diskann Erweiterung bietet Unterstützung für die Verwendung von DiskANN für effiziente Vektorindizierung und Suche.

Aktivieren von pg_diskann

Um die pg_diskann Erweiterung auf Ihrem Azure Database for PostgreSQL flexiblen Server zu verwenden, müssen Sie die Erweiterung auf Serverebene zulassen. Anschließend müssen Sie die Erweiterung für jede Datenbank erstellen, in der Sie die von der Erweiterung bereitgestellte Funktionalität verwenden möchten.

Da pg_diskann eine Abhängigkeit von der vector Erweiterung hat, können Sie entweder die Erweiterung in derselben Datenbank zulassen und vector oder den folgenden Befehl ausführen:

CREATE EXTENSION IF NOT EXISTS pg_diskann;

Alternativ können Sie das explizite Zulassen und Erstellen der vector Erweiterung überspringen und stattdessen den vorherigen Befehl ausführen, der die CASCADE Klausel anfügen soll. Diese Klausel weist PostgreSQL an, CREATE EXTENSION für die Erweiterung, von der es abhängt, implizit auszuführen. Führen Sie dazu den folgenden Befehl aus:

CREATE EXTENSION IF NOT EXISTS pg_diskann CASCADE;

Führen Sie den folgenden Befehl aus, um die Erweiterung aus der Datenbank abzulegen, mit der Sie derzeit verbunden sind:

DROP EXTENSION IF EXISTS pg_diskann;

Verwenden der Diskann-Indexzugriffsmethode

Nachdem Sie die Erweiterung installiert haben, können Sie einen diskann Index für eine Tabellenspalte erstellen, die Vektordaten enthält. Wenn Sie beispielsweise einen Index für die embedding-Spalte der demo-Tabelle erstellen möchten, verwenden Sie den folgenden Befehl:

CREATE TABLE demo (
 id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
 embedding public.vector(3)
 -- other columns
);

-- insert dummy data
INSERT INTO demo (embedding) VALUES
('[1.0, 2.0, 3.0]'),
('[4.0, 5.0, 6.0]'),
('[7.0, 8.0, 9.0]');

-- create a diskann index by using Cosine distance operator
CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann (embedding vector_cosine_ops)

Nachdem Sie den Index erstellt haben, können Sie Abfragen ausführen, um die nächsten Nachbarn zu finden.

Die folgende Abfrage findet die fünf nächsten Nachbarn des Vektors [2.0, 3.0, 4.0]:

SELECT id, embedding
FROM demo
ORDER BY embedding <=> '[2.0, 3.0, 4.0]'
LIMIT 5;

Postgres entscheidet automatisch, wann der DiskANN-Index verwendet werden soll. Wenn das System in einem Szenario, in dem der Index verwendet werden soll, entscheidet, den Index nicht zu verwenden, führen Sie den folgenden Befehl aus:

-- Explicit Transcation block to force use for DiskANN index.

BEGIN;
SET LOCAL enable_seqscan TO OFF;
-- Similarity search queries
COMMIT;

Von Bedeutung

Das Deaktivieren von enable_seqscan hält den Abfrageplaner davon ab, einen Plan für sequenzielle Scans zu verwenden, wenn andere Methoden verfügbar sind. Da sie mithilfe des SET LOCAL Befehls deaktiviert ist, wird die Einstellung nur für die aktuelle Transaktion wirksam. Nach einem COMMIT oder ROLLBACK wird wieder die Einstellung auf Sitzungsebene wirksam. Wenn die Abfrage andere Tabellen umfasst, entmutigt die Einstellung auch die Verwendung sequenzieller Scans in allen Tabellen.

Effiziente Skalierung mit Quantisierung (Vorschau)

DiskANN verwendet die Produktquantisierung (Product Quantization, PQ), um den Speicherbedarf der Vektoren erheblich zu reduzieren. Im Gegensatz zu anderen Quantisierungstechniken kann der PQ-Algorithmus Vektoren effektiver komprimieren und die Leistung erheblich verbessern.  Mithilfe von PQ kann DiskANN mehr Daten im Arbeitsspeicher speichern, den Zugriff auf langsameren Speicher reduzieren und beim Vergleich komprimierter Vektoren weniger Berechnen verwenden. Dies führt zu einer besseren Leistung und erheblichen Kosteneinsparungen beim Arbeiten mit größeren Datenmengen (> 1 Million Zeilen).

Von Bedeutung

Die Unterstützung der Produktquantisierung in DiskANN ist ab pg_diskann v0.6 und höher verfügbar.

Verwenden Sie PQ, um die Größe ihres Indexes zu reduzieren und mehr Daten in den Arbeitsspeicher zu integrieren:

CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann(embedding vector_cosine_ops) 
WITH(
    product_quantized=true
    );    

Verbessern der Genauigkeit bei Verwendung von PQ mit Vektor-Reranking

Die Neusortierung mit vollständigen Vektoren ist eine Technik, die in ANN-Suchsystemen (Approximate Nearest Neighbor) wie DiskANN mit Produktquantisierung (PQ) verwendet wird, um die Ergebnisgenauigkeit zu verbessern, indem die top-N abgerufenen Kandidaten mithilfe der ursprünglichen, nicht komprimierten (vollständigen) Vektoren neu angeordnet werden. Diese Reranking-Technik basiert ausschließlich auf exakten Vektorverknöhnungsmetriken (z. B. Kosinusähnlichkeit oder Euklidischer Abstand). Diese Technik ist nicht identisch mit der Neusortierung mithilfe eines Bewertungsmodells.

Um Geschwindigkeit und Präzision bei der Vektorgleichheitssuche auszugleichen, implementieren Sie beim Abfragen mit DiskANN und der Produktquantisierung eine zweistufige Reranking-Strategie, um die Genauigkeit zu verbessern.

  1. Ursprüngliche ungefähre Suche: Die innere Abfrage verwendet DiskANN, um die ersten 50 ungefähren nächsten Nachbarn basierend auf dem Kosinusabstand zwischen den gespeicherten Einbettungen und dem Abfragevektor abzurufen. Dieser Schritt ist schnell und effizient und nutzt die Indizierungsfunktionen von DiskANN.

  2. Präzise Neusortierung: Die äußere Abfrage sortiert diese 50 Ergebnisse nach ihrem tatsächlich berechneten Abstand neu und gibt die 10 relevantesten Übereinstimmungen zurück:

Hier sehen Sie ein Beispiel für eine Neurankung mit diesem zweistufigen Ansatz:

SELECT id
FROM (
    SELECT id, embedding <=> %s::vector AS distance
    FROM demo
    ORDER BY embedding <=> %s::vector asc
    LIMIT 50
) AS t
ORDER BY t.distance
LIMIT 10;

Hinweis

Ersetzen Sie %s durch den Abfragevektor. Sie können azure_ai verwenden, um direkt in Postgres einen Abfragevektor zu erstellen.

Mit diesem Ansatz wird ein Gleichgewicht zwischen Geschwindigkeit (über die ungefähre Suche) und Genauigkeit (über vollständige Vektorneusortierung) geschaffen, um qualitativ hochwertige Ergebnisse sicherzustellen, ohne das gesamte Dataset zu scannen.

Unterstützung für Einbettungen mit hoher Anzahl von Dimensionen

Erweiterte generative KI-Anwendungen basieren häufig auf Einbettungsmodellen mit einer hohen Anzahl von Dimensionen wie text-embedding-3-large, um eine hervorragende Genauigkeit zu erzielen. Herkömmliche Indizierungsmethoden wie HNSW in pgvector sind jedoch auf Vektoren mit bis zu 2.000 Dimensionen beschränkt, wodurch die Verwendung dieser leistungsstarken Modelle eingeschränkt wird.

Ab pg_diskann v0.6 und höher unterstützt DiskANN Indizierungsvektoren mit bis zu 16.000 Dimensionen, was den Umfang für KI-Workloads mit hoher Genauigkeit erheblich erweitert.

Von Bedeutung

Aktivieren Sie die Produktquantisierung, um die hochdimensionale Unterstützung zu nutzen.

Empfohlene Einstellungen:

  • product_quantized: Auf TRUE festgelegt
  • pq_param_num_chunks: Legen Sie den Wert auf ein Drittel der Einbettungsdimension fest, um eine optimale Leistung zu erzielen.
  • pq_param_training_samples: Wird basierend auf der Tabellengröße automatisch bestimmt, sofern der Wert nicht explizit festgelegt wird.

Diese Erweiterung ermöglicht eine skalierbare, effiziente Suche über große Vektordatensätze hinweg und behält gleichzeitig eine hohe Abrufrate und Genauigkeit bei.

Beschleunigung des Indexaufbaus

Um die Indexbuildzeiten zu verbessern, probieren Sie die folgenden Empfehlungen aus.

Mehr Arbeitsspeicher verwenden

Um die Erstellung des Indexes zu beschleunigen, erhöhen Sie den auf Ihrem PostgreSQL-Server zugewiesenen Speicher für den Indexbuild. Geben Sie die Speicherauslastung über den maintenance_work_mem Parameter an.

-- Set the parameters
SET maintenance_work_mem = '8GB'; -- Depending on your resources

Der CREATE INDEX Befehl verwendet den angegebenen Arbeitsspeicher, abhängig von den verfügbaren Ressourcen, um den Index zu erstellen.

CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann (embedding vector_cosine_ops)

Tipp

Skalieren Sie ihre Speicherressourcen während des Indexbuilds, um die Indizierungsgeschwindigkeit zu verbessern, und skalieren Sie dann nach Abschluss der Indizierung wieder nach unten.

Verwenden der Parallelisierung

Verwenden Sie parallele Worker, um die Erstellung des Indexes zu beschleunigen. Geben Sie die Anzahl der Worker über den parallel_workers Speicherparameter der CREATE TABLE Anweisung beim Erstellen der Tabelle an. Sie können diese Zahl später mithilfe der SET-Klausel der ALTER TABLE-Anweisung anpassen.

CREATE TABLE demo (
	id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
	embedding public.vector(3)
) WITH (parallel_workers = 4);
ALTER TABLE demo SET (parallel_workers = 8);

Der CREATE INDEX Befehl verwendet die angegebene Anzahl paralleler Worker, abhängig von den verfügbaren Ressourcen, um den Index zu erstellen.

CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann (embedding vector_cosine_ops)

Von Bedeutung

Der Leiterprozess kann nicht an parallelen Indexbuilds teilnehmen.

Wenn Sie den Index mithilfe paralleler Workerprozesse erstellen möchten, legen Sie die max_parallel_workers-, max_worker_processes- und max_parallel_maintenance_workers-Parameter entsprechend fest. Weitere Informationen zu diesen Parametern finden Sie unter Parametern, die Ressourcenverwendungen und asynchrones Verhalten steuern.

Legen Sie diese Parameter auf unterschiedlichen Granularitätsebenen fest. Um sie beispielsweise auf Sitzungsebene festzulegen, führen Sie die folgenden Anweisungen aus:

-- Set the parameters
SET max_parallel_workers = 8;
SET max_worker_processes = 8; -- Note: Requires server restart
SET max_parallel_maintenance_workers = 4;

Weitere Informationen zu anderen Optionen zum Konfigurieren dieser Parameter in Azure Database for PostgreSQL flexiblen Server finden Sie unter Configure-Parameter.

Hinweis

Für den max_worker_processes Parameter muss ein Serverneustart wirksam werden.

Wenn die Konfiguration dieser Parameter und der verfügbaren Ressourcen auf dem Server nicht das Starten der parallelen Worker erlaubt, fällt PostgreSQL automatisch zurück, um den Index im nichtparallel-Modus zu erstellen.

Konfigurationsparameter

Wenn Sie einen diskann Index erstellen, geben Sie verschiedene Parameter an, um das Verhalten zu steuern.

Indexparameter

  • max_neighbors: Maximale Anzahl von Kanten pro Knoten im Diagramm Der Standardwert ist 32. Ein höherer Wert kann den Rückruf bis zu einem bestimmten Punkt verbessern.
  • l_value_ib: Größe der Suchliste während des Indexbuilds. Der Standardwert ist 100. Ein höherer Wert macht den Build langsamer, aber der Index ist von höherer Qualität.
  • product_quantized: Ermöglicht die Produktquantisierung für eine effizientere Suche. Der Standardwert ist "false".
  • pq_param_num_chunks: Anzahl der Blöcke für die Produktquantisierung. Der Standardwert ist 0, was bedeutet, dass das System automatisch den Wert basierend auf den Einbettungsabmessungen bestimmt. Verwenden Sie ein Drittel der ursprünglichen Einbettungsabmessungen.
  • pq_param_training_samples: Anzahl der Vektoren, mit denen die PQ-Pivot-Tabelle trainiert wird. Der Standardwert ist 0, was bedeutet, dass das System den Wert basierend auf der Tabellengröße automatisch bestimmt.
CREATE INDEX demo_embedding_diskann_custom_idx ON demo USING diskann (embedding vector_cosine_ops)
WITH (
 max_neighbors = 48,
 l_value_ib = 100,
 product_quantized=true, 
 pq_param_num_chunks = 0,
 pq_param_training_samples = 0
 );

Erweiterungsparameter

  • diskann.iterative_search: Steuert das Suchverhalten.

    Konfigurationen für diskann.iterative_search:

    • relaxed_order (Standard): ermöglicht diskann das iterative Durchsuchen des Graphen in Batches von diskann.l_value_is, bis die gewünschte Anzahl von Tupeln (möglicherweise durch die LIMIT-Klausel begrenzt) zurückgegeben wird Diese Option kann dazu führen, dass die Ergebnisse nicht mehr in ordnung sind.

    • strict_order: Ähnlich relaxed_orderwie , aber es stellt sicher, dass die Ergebnisse in strenger Reihenfolge nach Entfernung sortiert zurückgegeben werden.

    • off: Verwendet nichtiterative Suchfunktionen. Es versucht, diskann.l_value_is Tupel in einem Schritt abzurufen. Die nichtiterative Suche kann nur ein Maximum von diskann.l_value_is Vektoren für eine Abfrage zurückgeben, unabhängig von der LIMIT Klausel oder der Anzahl der Tupel, die der Abfrage entsprechen.

    Um das Suchverhalten für alle in der aktuellen Sitzung ausgeführten Abfragen auf strict_order festzulegen, führen Sie die folgende Anweisung aus:

    SET diskann.iterative_search TO 'strict_order';
    

    Führen Sie die folgende Anweisung aus, um sie so zu ändern, dass sie sich nur auf alle Abfragen auswirkt, die in der aktuellen Transaktion ausgeführt werden:

    BEGIN;
    SET LOCAL diskann.iterative_search TO 'strict_order';
    -- All your queries
    COMMIT;
    
  • diskann.l_value_is: L-Wert für die Indexüberprüfung (Standardwert ist 100). Das Erhöhen des Werts verbessert den Recall, kann aber Abfragen verlangsamen.

    Um den L-Wert für die Indexüberprüfung für alle in der aktuellen Sitzung ausgeführten Abfragen in 20 zu ändern, führen Sie die folgende Anweisung aus:

    SET diskann.l_value_is TO 20;
    

    Führen Sie die folgende Anweisung aus, um sie so zu ändern, dass sie sich nur auf alle Abfragen auswirkt, die in der aktuellen Transaktion ausgeführt werden:

    BEGIN;
    SET LOCAL diskann.l_value_is TO 20;
    -- All your queries
    COMMIT;
    
Datasetgröße (Zeilen) Parametertyp Name Empfohlener Wert
<1 Mio. Indexerstellung l_value_ib 100
<1 Mio. Indexerstellung max_neighbors 32
<1 Mio. Abfragezeit diskann.l_value_is 100
 
1M-50M Indexerstellung l_value_ib 100
1M-50M Indexerstellung max_neighbors 64
1M-50M Indexerstellung product_quantized Wahr
1M-50M Abfragezeit diskann.l_value_is 100
 
>50M Indexerstellung l_value_ib 100
>50M Indexerstellung max_neighbors 96
>50M Indexerstellung product_quantized Wahr
>50M Abfragezeit diskann.l_value_is 100

Hinweis

Diese Parameter können je nach spezifischem Dataset und Anwendungsfall variieren. Möglicherweise müssen Sie mit verschiedenen Parameterwerten experimentieren, um die optimalen Einstellungen für Ihr bestimmtes Szenario zu finden.

Fortschritt von CREATE INDEX und REINDEX

Ab PostgreSQL 12 können Sie mit pg_stat_progress_create_index den Fortschritt von CREATE INDEX- oder REINDEX-Operationen prüfen.

SELECT phase, round(100.0 * blocks_done / nullif(blocks_total, 0), 1) AS "%" FROM pg_stat_progress_create_index;

Weitere Informationen zu den möglichen Phasen, in denen ein CREATE INDEX- oder REINDEX-Vorgang ausgeführt wird, finden Sie unter CREATE INDEX-Phasen.

Auswählen der Indexzugriffsfunktion

Der Vektortyp unterstützt drei Suchtypen für die gespeicherten Vektoren. Wählen Sie die richtige Zugriffsfunktion für Ihren Index aus, damit die Datenbank den Index berücksichtigen kann, wenn Sie Ihre Abfragen ausführen.

pg_diskann unterstützt die folgenden Entfernungsoperatoren:

  • vector_l2_ops: <-> Euklidischer Abstand
  • vector_cosine_ops: <=> Kosinusabstand
  • vector_ip_ops: <#> Inneres Produkt

Problembehandlung

Fehler: : assertion left == right failed left: 40 right: 0

  • DiskANN GA Version, v0.6.x, führt zu wichtigen Änderungen im Indexmetadatenformat. Mit v0.5.x erstellte Indizes sind nicht vorwärtskompatibel mit v0.6.x-Einfügevorgängen. Wenn Sie versuchen, eine Tabelle mit einem veralteten Index einzufügen, wird eine Fehlermeldung angezeigt, auch wenn der Index gültig ist.

  • Wenn dieser Fehler auftritt, beheben Sie ihn wie folgt:

    • Option 1: Ausführen der Anweisung REINDEX oder REDINDEX CONCURRENTLY für den Index.

    • Option 2: Neuerstellen des Indexes.

      DROP INDEX your_index_name;
      CREATE INDEX your_index_name ON your_table USING diskann(your_vector_column vector_cosine_ops);
      
      

Fehler: : diskann index needs to be upgraded to version 2...

  • Wenn dieser Fehler auftritt, beheben Sie ihn wie folgt:
    • Option 1: Ausführen der Anweisung REINDEX oder REDINDEX CONCURRENTLY für den Index.

    • Option 2: Da REINDEX möglicherweise lange dauern kann, stellt die Erweiterung auch eine benutzerdefinierte Funktion namens upgrade_diskann_index() bereit, die Ihren Index schneller aktualisiert, wenn möglich.

      Führen Sie zum Aktualisieren des Indexes die folgende Anweisung aus:

      SELECT upgrade_diskann_index('demo_embedding_diskann_custom_idx');
      

      Führen Sie die folgende Anweisung aus, um alle Diskann-Indizes in der Datenbank auf die aktuelle Version zu aktualisieren:

      SELECT upgrade_diskann_index(pg_class.oid)
      FROM pg_class
      JOIN pg_am ON (pg_class.relam = pg_am.oid)
      WHERE pg_am.amname = 'diskann';