In diesem Dokument wird beschrieben, wie Sie Ihre Indexe optimieren, um eine schnellere Abfrageleistung und einen besseren Recall zu erzielen.
ScaNN
-Index optimieren
Der ScaNN-Index verwendet eine baumbasierte Quantisierung. Bei der Baumquantisierung wird ein Suchbaum zusammen mit einer Quantisierungs- oder Hash-Funktion gelernt. Wenn Sie eine Abfrage ausführen, wird der Suchbaum verwendet, um den Suchraum zu verkleinern, während die Quantisierung zur Komprimierung der Indexgröße dient. Durch diese Bereinigung wird die Berechnung der Ähnlichkeit (d.h. des Abstands) zwischen dem Anfragevektor und den Datenbankvektoren beschleunigt.
Um sowohl eine hohe QPS-Rate (Queries per Second, Abfragen pro Sekunde) als auch einen hohen Recall bei Ihren Nearest-Neighbor-Abfragen zu erzielen, müssen Sie den Baum Ihres ScaNN
-Index so partitionieren, dass er am besten zu Ihren Daten und Abfragen passt.
Bevor Sie einen ScaNN
-Index erstellen, müssen Sie Folgendes tun:
- Prüfen Sie, ob bereits eine Tabelle mit Ihren Daten erstellt wurde.
- Achten Sie darauf, dass der Wert, den Sie für das Flag
maintenance_work_mem
undshared_buffers
festlegen, kleiner als der Gesamtspeicher der Maschine ist, um Probleme beim Generieren des Index zu vermeiden.
Parameter für die Abstimmung
Die folgenden Indexparameter und Datenbank-Flags werden zusammen verwendet, um das richtige Gleichgewicht zwischen Recall und QPS zu finden. Alle Parameter gelten für beide ScaNN
-Indextypen.
Abstimmungsparameter | Beschreibung | Parametertyp |
---|---|---|
num_leaves |
Die Anzahl der Partitionen, die auf diesen Index angewendet werden sollen. Die Anzahl der Partitionen, die Sie beim Erstellen eines Index anwenden, wirkt sich auf die Indexleistung aus. Wenn Sie die Anzahl der Partitionen für eine bestimmte Anzahl von Vektoren erhöhen, erstellen Sie einen detaillierteren Index, der den Recall und die Abfrageleistung verbessert. Dies führt jedoch zu längeren Indexerstellungszeiten. Da dreistufige Bäume schneller erstellt werden als zweistufige Bäume, können Sie den Wert von num_leaves_value beim Erstellen eines dreistufigen Baumindex erhöhen, um eine bessere Leistung zu erzielen.
|
Index erstellen |
quantizer |
Der Typ des Quantizers, den Sie für den K-Means-Baum verwenden möchten. Der Standardwert ist SQ8 , um die Abfrageleistung zu verbessern.Legen Sie ihn auf FLAT fest, um den Recall zu verbessern. |
Index erstellen |
enable_pca |
Aktiviert die Hauptkomponentenanalyse (Principal Component Analysis, PCA). Das ist eine Technik zur Dimensionsreduzierung, mit der die Größe des Einbettungsvektors automatisch reduziert wird, wenn möglich. Diese Option ist standardmäßig aktiviert. Setzen Sie sie auf false , wenn Sie eine Verschlechterung des Erinnerungsvermögens feststellen. |
Index erstellen |
scann.num_leaves_to_search |
Das Datenbank-Flag steuert den Kompromiss zwischen Trefferquote und QPS. Der Standardwert ist 1% des in num_leaves festgelegten Werts. Je höher der festgelegte Wert, desto besser ist der Recall, aber desto niedriger ist die QPS. Das gilt auch umgekehrt. |
Laufzeit der Abfrage |
scann.max_top_neighbors_buffer_size |
Das Datenbankflag gibt die Größe des Cache an, der verwendet wird, um die Leistung für gefilterte Abfragen zu verbessern. Dazu werden die gescannten Kandidatennachbarn im Arbeitsspeicher anstelle auf der Festplatte bewertet oder eingestuft. Der Standardwert ist 20000 . Je höher der festgelegte Wert, desto besser ist die QPS bei gefilterten Abfragen. Dies führt jedoch zu einer höheren Arbeitsspeichernutzung und umgekehrt. |
Laufzeit der Abfrage |
scann.pre_reordering_num_neighbors |
Das Datenbankflag gibt an, wie viele Kandidatennachbarn in den Neusortierungsphasen berücksichtigt werden sollen, nachdem bei der ersten Suche eine Reihe von Kandidaten ermittelt wurde. Legen Sie hier einen Wert fest, der höher ist als die Anzahl der Nachbarn, die von der Abfrage zurückgegeben werden sollen. Höhere Werte führen zu einem besseren Recall, aber auch zu einer geringeren Anzahl von Anfragen pro Sekunde. |
Laufzeit der Abfrage |
max_num_levels |
Die maximale Anzahl von Ebenen des K-Means-Clustering-Baums.
|
Index erstellen |
ScaNN
-Index optimieren
Sehen Sie sich die folgenden Beispiele für ScaNN
-Indexe mit zwei und drei Ebenen an, um zu sehen, wie die Optimierungsparameter festgelegt werden:
Index mit zwei Ebenen
SET LOCAL scann.num_leaves_to_search = 1;
SET LOCAL scann.pre_reordering_num_neighbors=50;
CREATE INDEX my-scann-index ON my-table
USING scann (vector_column cosine)
WITH (num_leaves = [power(1000000, 1/2)]);
Index mit drei Ebenen
SET LOCAL scann.num_leaves_to_search = 10;
SET LOCAL scann.pre_reordering_num_neighbors=50;
CREATE INDEX my-scann-index ON my-table
USING scann (vector_column cosine)
WITH (num_leaves = [power(1000000, 2/3)], max_num_levels = 2);
Jeder Einfüge- oder Aktualisierungsvorgang für eine Tabelle, für die bereits ein ScaNN
-Index generiert wurde, wirkt sich darauf aus, wie der gelernte Baum den Index optimiert. Wenn Ihre Tabelle häufig aktualisiert oder neue Zeilen eingefügt werden, empfehlen wir, den vorhandenen ScaNN
-Index regelmäßig neu zu indexieren, um die Genauigkeit des Rückrufs zu verbessern.
Sie können Indexmesswerte überwachen, um die Anzahl der Änderungen zu ermitteln, die seit der Erstellung des Index vorgenommen wurden, und den Index entsprechend neu indexieren. Weitere Informationen zu Messwerten finden Sie unter Messwerte für Vektorindex.
Best Practices für die Optimierung
Je nach Art des ScaNN
-Index, den Sie verwenden möchten, variieren die Empfehlungen zum Optimieren des Index. In diesem Abschnitt finden Sie Empfehlungen zum Optimieren von Indexparametern, um ein optimales Gleichgewicht zwischen Recall und QPS zu erreichen.
Zweistufiger Baumindex
So wenden Sie Empfehlungen an, um die optimalen Werte für num_leaves
und num_leaves_to_search
für Ihren Datensatz zu ermitteln:
- Erstellen Sie den Index
ScaNN
mitnum_leaves
, das auf die Quadratwurzel der Zeilenanzahl der indexierten Tabelle festgelegt ist. - Führen Sie Ihre Testabfragen aus und erhöhen Sie den Wert von
scann.num_of_leaves_to_search
, bis Sie den gewünschten Recall-Bereich erreichen, z. B. 95%. Weitere Informationen zum Analysieren von Abfragen finden Sie unter Abfragen analysieren. - Notieren Sie sich das Verhältnis zwischen
scann.num_leaves_to_search
undnum_leaves
, das in den nachfolgenden Schritten verwendet wird. Dieses Verhältnis bietet eine Annäherung an den Datensatz, mit dem Sie den angestrebten Recall erreichen können.
Wenn Sie mit Vektoren mit hoher Dimensionalität (500 Dimensionen oder mehr) arbeiten und den Recall verbessern möchten, versuchen Sie, den Wert vonscann.pre_reordering_num_neighbors
zu optimieren. Legen Sie den Wert als Ausgangspunkt auf100 * sqrt(K)
fest, wobeiK
das Limit ist, das Sie in Ihrer Abfrage festgelegt haben. - Wenn Ihre Rate von Abfragen pro Sekunde zu niedrig ist, nachdem Ihre Anfragen ein bestimmtes Ziel für den Recall erreicht haben, gehen Sie so vor:
- Erstellen Sie den Index neu und erhöhen Sie den Wert von
num_leaves
undscann.num_leaves_to_search
gemäß der folgenden Anleitung:- Setzen Sie
num_leaves
auf einen größeren Faktor der Quadratwurzel der Anzahl der Zeilen. Wenn der Index beispielsweisenum_leaves
auf die Quadratwurzel der Zeilenanzahl festgelegt hat, versuchen Sie, ihn auf das Doppelte der Quadratwurzel festzulegen. Wenn der Wert bereits verdoppelt wurde, versuchen Sie, ihn auf das Dreifache der Quadratwurzel zu setzen. - Erhöhen Sie
scann.num_leaves_to_search
nach Bedarf, um das Verhältnis zunum_leaves
beizubehalten, das Sie in Schritt 3 notiert haben. - Legen Sie für
num_leaves
einen Wert fest, der kleiner oder gleich der Zeilenanzahl geteilt durch 100 ist.
- Setzen Sie
- Führen Sie die Testabfragen noch einmal aus.
Während Sie die Testanfragen ausführen, können Sie mit einer Reduzierung von
scann.num_leaves_to_search
experimentieren, um einen Wert zu finden, der die Anzahl der Abfragen pro Sekunde erhöht und gleichzeitig die Trefferquote hoch hält. Sie können verschiedene Werte fürscann.num_leaves_to_search
ausprobieren, ohne den Index neu erstellen zu müssen.
- Erstellen Sie den Index neu und erhöhen Sie den Wert von
- Wiederholen Sie Schritt 4, bis sowohl die QPS als auch der Recall-Bereich akzeptable Werte erreicht haben.
Baumindex mit drei Ebenen
Zusätzlich zu den Empfehlungen für den ScaNN
-Index mit zwei Ebenen sollten Sie die folgenden Richtlinien und Schritte zur Optimierung des Index verwenden:
- Wenn Sie die
max_num_levels
für einen Baum mit zwei Ebenen von1
auf2
für einen Baum mit drei Ebenen erhöhen, verkürzt sich die Zeit zum Erstellen eines Index erheblich, allerdings auf Kosten der Recall-Genauigkeit. Legen Siemax_num_levels
anhand der folgenden Empfehlung fest:- Legen Sie den Wert auf
2
fest, wenn die Anzahl der Vektorzeilen 100 Millionen überschreitet. - Legen Sie den Wert auf
1
fest, wenn die Anzahl der Vektorzeilen weniger als 10 Millionen beträgt. - Legen Sie den Wert auf
1
oder2
fest, wenn die Anzahl der Vektorzeilen zwischen 10 Millionen und 100 Millionen liegt. Die Entscheidung hängt davon ab, wie wichtig Ihnen die Indexerstellungszeit und die Recall-Genauigkeit sind.
- Legen Sie den Wert auf
So wenden Sie Empfehlungen an, um den optimalen Wert der Indexparameter num_leaves
und max_num_levels
zu ermitteln:
Erstellen Sie den
ScaNN
-Index mit den folgendennum_leaves
- undmax_num_levels
-Kombinationen basierend auf Ihrem Dataset:- Vektorzeilen mit mehr als 100 Millionen Zeilen: Legen Sie
max_num_levels
als2
undnum_leaves
alspower(rows, ⅔)
fest. - Vektorzeilen mit weniger als 100 Millionen Zeilen: Legen Sie
max_num_levels
als1
undnum_leaves
alssqrt(rows)
fest. - Vektorzeilen zwischen 10 Millionen und 100 Millionen Zeilen: Legen Sie zuerst
max_num_levels
als1
undnum_leaves
alssqrt(rows)
fest.
- Vektorzeilen mit mehr als 100 Millionen Zeilen: Legen Sie
Führen Sie Ihre Testabfragen aus. Weitere Informationen zum Analysieren von Abfragen finden Sie unter Abfragen analysieren.
Wenn die Indexerstellungszeit zufriedenstellend ist, behalten Sie den
max_num_levels
-Wert bei und testen Sie dennum_leaves
-Wert, um die optimale Genauigkeit des Rückrufs zu ermitteln.Wenn Sie mit der Indexierungszeit nicht zufrieden sind, gehen Sie so vor:
Wenn der Wert von
max_num_levels
1
ist, wird der Index gelöscht. Erstellen Sie den Index neu und legen Sie den Wertmax_num_levels
auf2
fest.Führen Sie die Abfragen aus und passen Sie den
num_leaves
-Wert an, um eine optimale Trefferquoten-Genauigkeit zu erzielen.Wenn der Wert von
max_num_levels
2
ist, wird der Index gelöscht. Erstellen Sie den Index mit demselbenmax_num_levels
-Wert neu und optimieren Sie dennum_leaves
-Wert für eine optimale Genauigkeit des Rückrufs.
IVF
-Index optimieren
Durch Anpassen der Werte, die Sie für die Parameter lists
, ivf.probes
und quantizer
festlegen, lässt sich die Leistung Ihrer Anwendung möglicherweise optimieren:
Abstimmungsparameter | Beschreibung | Parametertyp |
---|---|---|
lists |
Die Anzahl der Listen, die beim Erstellen des Index erstellt wurden. Der Ausgangspunkt für die Festlegung dieses Werts ist (rows)/1000 für bis zu einer Million Zeilen und sqrt(rows) für mehr als eine Million Zeilen. |
Index erstellen |
quantizer |
Der Typ des Quantizers, den Sie für den K-Means-Baum verwenden möchten. Der Standardwert ist SQ8 , um die Abfrageleistung zu verbessern. Stelle sie auf FLAT ein, um die Erinnerung zu verbessern. |
Index erstellen |
ivf.probes |
Die Anzahl der nächsten Listen, die bei der Suche untersucht werden sollen. Der Ausgangspunkt für diesen Wert ist sqrt(lists) . |
Laufzeit der Abfrage |
Im folgenden Beispiel sehen Sie einen IVF
-Index mit den festgelegten Optimierungsparametern:
SET LOCAL ivf.probes = 10;
CREATE INDEX my-ivf-index ON my-table
USING ivf (vector_column cosine)
WITH (lists = 100, quantizer = 'SQ8');
IVFFlat
-Index optimieren
Durch Anpassen der Werte, die Sie für die Parameter lists
und ivfflat.probes
festlegen, können Sie die Anwendungsleistung optimieren:
Abstimmungsparameter | Beschreibung | Parametertyp |
---|---|---|
lists |
Die Anzahl der Listen, die beim Erstellen des Index erstellt wurden. Der Ausgangspunkt für die Festlegung dieses Werts ist (rows)/1000 für bis zu einer Million Zeilen und sqrt(rows) für mehr als eine Million Zeilen. |
Index erstellen |
ivfflat.probes |
Die Anzahl der Listen mit den nächsten Nachbarn, die bei der Suche untersucht werden sollen. Der Ausgangspunkt für diesen Wert ist sqrt(lists) . |
Laufzeit der Abfrage |
Bevor Sie einen IVFFlat
-Index erstellen, muss das max_parallel_maintenance_workers
-Flag Ihrer Datenbank auf einen Wert gesetzt sein, der ausreicht, um die Indexerstellung für große Tabellen zu beschleunigen.
Im folgenden Beispiel sehen Sie einen IVFFlat
-Index mit den festgelegten Optimierungsparametern:
SET LOCAL ivfflat.probes = 10;
CREATE INDEX my-ivfflat-index ON my-table
USING ivfflat (vector_column cosine)
WITH (lists = 100);
HNSW
-Index optimieren
Durch Anpassen der Werte, die Sie für die Parameter m
, ef_construction
und hnsw.ef_search
festlegen, lässt sich die Anwendungsleistung optimieren.
Abstimmungsparameter | Beschreibung | Parametertyp |
---|---|---|
m |
Die maximale Anzahl von Verbindungen pro Knoten im Diagramm. Sie können mit dem Standardwert 16 (default) beginnen und je nach Größe Ihres Datasets höhere Werte ausprobieren. |
Index erstellen |
ef_construction |
Die Größe der dynamischen Kandidatenliste, die während der Erstellung des Diagramms verwaltet wird. Sie wird ständig aktualisiert und enthält die aktuell besten Kandidaten für die nächsten Nachbarn eines Knotens. Legen Sie für diesen Wert einen beliebigen Wert fest, der höher als das Doppelte des m -Werts ist, z. B. 64 (Standard). |
Index erstellen |
ef_search |
Die Größe der dynamischen Kandidatenliste, die bei der Suche verwendet wird. Sie können diesen Wert zuerst auf m oder ef_construction festlegen und ihn dann ändern, während Sie den Recall beobachten. Der Standardwert ist 40 . |
Laufzeit der Abfrage |
Im folgenden Beispiel sehen Sie einen hnsw
-Index mit den festgelegten Optimierungsparametern:
SET LOCAL hnsw.ef_search = 40;
CREATE INDEX my-hnsw-index ON my-table
USING hnsw (vector_column cosine)
WITH (m = 16, ef_construction = 200);
Abfragen analysieren
Verwenden Sie den Befehl EXPLAIN ANALYZE
, um Ihre Abfragestatistiken zu analysieren, wie in der folgenden SQL-Beispielabfrage gezeigt.
EXPLAIN ANALYZE SELECT result-column FROM my-table
ORDER BY EMBEDDING_COLUMN ::vector
USING INDEX my-scann-index
<-> embedding('textembedding-gecko@003', 'What is a database?')
LIMIT 1;
Die Beispielantwort QUERY PLAN
enthält Informationen wie die benötigte Zeit, die Anzahl der gescannten oder zurückgegebenen Zeilen und die verwendeten Ressourcen.
Limit (cost=0.42..15.27 rows=1 width=32) (actual time=0.106..0.132 rows=1 loops=1)
-> Index Scan using my-scann-index on my-table (cost=0.42..858027.93 rows=100000 width=32) (actual time=0.105..0.129 rows=1 loops=1)
Order By: (embedding_column <-> embedding('textgecko@003', 'What is a database?')::vector(768))
Limit value: 1
Planning Time: 0.354 ms
Execution Time: 0.141 ms
Messwerte für Vektorindexe ansehen
Mithilfe der Messwerte für Vektorindexe können Sie die Leistung Ihres Vektorindex überprüfen, Bereiche für Verbesserungen identifizieren und den Index bei Bedarf anhand der Messwerte optimieren.
Wenn Sie alle Messwerte für Vektorindexe aufrufen möchten, führen Sie die folgende SQL-Abfrage aus, in der die Ansicht pg_stat_ann_indexes
verwendet wird:
SELECT * FROM pg_stat_ann_indexes;
Weitere Informationen zur vollständigen Liste der Messwerte finden Sie unter Messwerte für Vektorindex.