Freigeben über


Aktivieren und Verwenden der DiskANN-Erweiterung

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 in Ihrer Azure-Datenbank für flexible Serverinstanz von PostgreSQL zu verwenden, müssen Sie die Erweiterung auf Instanzebene 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 die Erweiterung installiert wurde, 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 der Index erstellt wurde, können Sie Abfragen ausführen, um die nächsten Nachbarn zu finden.

Die folgende Abfrage findet die 5 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 der Index in einem Szenario nicht verwendet werden soll, in dem Sie ihn verwenden möchten, 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;

Wichtig

Wenn enable_seqscan deaktiviert ist, hält dies den Planer davon ab, den Abfrageplaner für sequenzielle Überprüfungen zu verwenden, wenn andere Methoden verfügbar sind. Da sie mit dem SET LOCAL Befehl deaktiviert wird, wird die Einstellung nur für die aktuelle Transaktion wirksam. Nach einem COMMIT oder ROLLBACK wird wieder die Einstellung auf Sitzungsebene wirksam. Beachten Sie, dass die Einstellung, wenn die Abfrage andere Tabellen umfasst, auch davon abhält, sequenzielle Scans in allen Tabellen zu verwenden.

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.  DiskANN mit PQ kann mehr Daten im Arbeitsspeicher behalten, wodurch der Zugriff auf langsameren Speicher reduziert wird, und beim Vergleich komprimierter Vektoren weniger Rechenaufwand verwendet wird. Dies führt zu einer besseren Leistung und erheblichen Kosteneinsparungen beim Arbeiten mit größeren Datenmengen (> 1 Million Zeilen).

Wichtig

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

Um die Größe Ihres Indexes zu verringern und mehr Daten im Arbeitsspeicher unterzubringen, können Sie PQ verwenden:

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 Neusortierungstechnik basiert ausschließlich auf genauen Vektorähnlichkeitsmetriken (z. B. Kosinusähnlichkeit oder euklidischer Abstand). Diese Technik ist nicht identisch mit der Neusortierung mithilfe eines Bewertungsmodells.

Um bei der Vektorähnlichkeitssuche Geschwindigkeit und Genauigkeit im Gleichgewicht zu halten, kann bei Abfragen mit DiskANN und der Produktquantisierung eine zweistufige Neusortierungsstrategie implementiert werden, 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 Neusortierung mithilfe dieses 2-Schritt-Ansatzes:

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

%s sollte durch den Abfragevektor ersetzt werden. 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 jetzt Indizierungsvektoren mit bis zu 16.000 Dimensionen und erweitert den Anwendungsbereich für KI-Workloads mit hoher Genauigkeit erheblich.

Wichtig

Die Produktquantisierung muss aktiviert sein, um die Unterstützung einer hohen Anzahl von Dimensionen 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

Wir empfehlen einige Möglichkeiten, um die Indexbuildzeiten zu verbessern.

Verwenden von mehr Arbeitsspeicher

Um die Erstellung des Indexes zu beschleunigen, können Sie den in Ihrer Postgres-Instanz zugewiesenen Speicher für den Indexbuild erhöhen. Die Speicherauslastung kann über den maintenance_work_mem Parameter angegeben werden.

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

Anschließend CREATE INDEX verwendet der Befehl 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

Sie können ihre Speicherressourcen während des Indexbuilds skalieren, um die Indizierungsgeschwindigkeit zu verbessern, und dann nach Abschluss der Indizierung wieder herunterskalieren.

Verwenden der Parallelisierung

Um die Erstellung des Indexes zu beschleunigen, können Sie parallele Worker verwenden. Die Anzahl der Mitarbeiter kann durch den parallel_workers Speicherparameter der CREATE TABLE Anweisung angegeben werden, wenn sie die Tabelle erstellt. Sie kann später mithilfe der SET-Klausel der ALTER TABLE-Anweisung angepasst werden.

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

Anschließend verwendet der Befehl CREATE INDEX die angegebene Anzahl von parallelen Arbeitsprozessen, 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)

Wichtig

Der Leiterprozess kann nicht an parallelen Indexbuilds teilnehmen.

Wenn Sie den Index mithilfe von parallelen Workern erstellen möchten, müssen Sie auch die Parameter max_parallel_workers, max_worker_processes und max_parallel_maintenance_workers entsprechend festlegen. Weitere Informationen zu diesen Parametern finden Sie unter Parametern, die Ressourcenverwendungen und asynchrones Verhalten steuern.

Sie können diese Parameter auf unterschiedlichen Granularitätsebenen festlegen. Um sie beispielsweise auf Sitzungsebene festzulegen, können Sie die folgenden Anweisungen ausführen:

-- 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 flexible Server finden Sie unter Konfigurieren von Serverparametern.

Hinweis

Für den parameter max_worker_processes 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

Beim Erstellen eines diskann Indexes können Sie verschiedene Parameter angeben, um das Verhalten zu steuern.

Indexparameter

  • max_neighbors: maximale Anzahl von Kanten pro Knoten im Graph (Standardwert: 32) Ein höherer Wert kann den Rückruf bis zu einem bestimmten Punkt verbessern.
  • l_value_ib: Größe der Suchliste während der Indexerstellung (Standardwert: 100) Ein höherer Wert macht die Kompilierung langsamer, aber der Index ist von höherer Qualität.
  • product_quantized: Aktiviert die Produktquantisierung für eine effizientere Suche (Standardwert „false“).
  • pq_param_num_chunks: Anzahl der Blöcke für die Produktquantisierung (Standardwert: 0). 0 bedeutet, dass sie basierend auf den Einbettungsmaßen automatisch bestimmt wird. Es wird empfohlen, 1/3 der ursprünglichen Einbettungsabmessungen zu verwenden.
  • pq_param_training_samples: Anzahl der Vektoren zum Trainieren der PQ-Pivottable (Standardwert: 0). 0 bedeutet, dass sie basierend auf der Tabellengröße automatisch bestimmt wird.
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 Das kann dazu führen, dass die Ergebnisse nicht in der richtigen Reihenfolge sind.

    • strict_order: Ähnlich wie relaxed_order ermöglicht Diskann, den Graphen iterativ zu durchsuchen, bis die gewünschte Anzahl von Tupeln erhalten wird. Es stellt jedoch sicher, dass die Ergebnisse in strenger Reihenfolge sortiert nach Entfernung zurückgegeben werden.

    • off: Verwendet nicht iterative Suchfunktionen, was bedeutet, dass versucht wird, diskann.l_value_is Tupeln 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 zu strict_order ändern, führen Sie für alle abfragen, die in der aktuellen Sitzung ausgeführt werden, 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: 100). Das Erhöhen des Werts verbessert den Recall, kann aber Abfragen verlangsamen.

    Um den L-Wert für die Indexüberprüfung in 20 zu ändern, führen Sie für alle Abfragen, die in der aktuellen Sitzung ausgeführt werden, 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. Benutzer müssen möglicherweise mit verschiedenen Parameterwerten experimentieren, um die optimalen Einstellungen für ihr bestimmtes Szenario zu finden.

Fortschritt von CREATE INDEX und REINDEX

Mit PostgreSQL 12 und höher können Sie mit pg_stat_progress_create_index den Fortschritt der Vorgänge CREATE INDEX oder REINDEX überprü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 durchlaufen wird, finden Sie unter CREATE INDEX-Phasen.

Auswählen der Indexzugriffsfunktion

Mit dem Vektortyp können Sie drei Arten von Suchen für die gespeicherten Vektoren durchführen. Sie müssen die richtige Zugriffsfunktion für Ihren Index auswählen, 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, tritt ein Fehler auf, auch wenn der Index gültig ist.

  • Wenn dieser Fehler auftritt, können Sie folgendes beheben:

    • 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, können Sie folgendes beheben:
    • 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';