AISAQCompatible with Milvus 2.6.4+

AISAQ ist ein festplattenbasierter Vektorindex, der DISKANN erweitert, um Datensätze in Milliardengröße mit minimalem DRAM-Footprint zu verarbeiten.

Im Gegensatz zu DISKANN, das komprimierte Vektoren im Speicher hält, wurde AISAQ mit einer "Near-Zero-DRAM-Architektur" entwickelt, was bedeutet, dass alle Datenstrukturen auf SSD gespeichert werden.

AISAQ ermöglicht die Ausführung von Datenbanken mit extrem hohem Umfang unter Verwendung von Standardservern und bietet Betriebsmodi, die ein Gleichgewicht zwischen Leistung und Speicherkosten herstellen.

Wie AISAQ funktioniert

Das obige Diagramm vergleicht die Speicherlayouts von DISKANN, AISAQ-Performance und AISAQ-Scale und zeigt, wie die Daten (Rohvektoren, Kantenlisten und PQ-Codes) zwischen RAM und Festplatte verteilt werden.

Aisaq Vs Diskann Aisaq vs. Diskann

Grundlage: DISKANN-Zusammenfassung

Bei DISKANN werden die Rohvektoren und Kantenlisten auf der Festplatte gespeichert, während die PQ-komprimierten Vektoren im Speicher (DRAM) aufbewahrt werden.

Wenn DISKANN einen Knoten (z.B. Vektor 0) ansteuert:

  • Er lädt den Rohvektor(raw_vector_0) und seine Kantenliste(edgelist_0) von der Festplatte.

  • Die Kantenliste gibt an, welche Nachbarn als nächstes besucht werden sollen (in diesem Beispiel die Knoten 2, 3 und 5).

  • Der Rohvektor wird verwendet, um den genauen Abstand zum Abfragevektor für die Rangfolge zu berechnen.

  • Die PQ-Daten im Speicher werden für die ungefähre Abstandsfilterung verwendet, um den nächsten Durchlauf zu steuern.

Da die PQ-Daten bereits im DRAM zwischengespeichert sind, ist für jeden Knotenbesuch nur eine Festplatten-E/A erforderlich, wodurch eine hohe Abfragegeschwindigkeit bei moderater Speichernutzung erreicht wird.

Eine ausführliche Erläuterung dieser Komponenten und Parameter finden Sie unter DISKANN.

AISAQ-Betriebsmodi

AISAQ bietet zwei Betriebsmodi, um zwei unterschiedliche Anwendungsfälle abzudecken:

Leistungsmodus: Optimiert für Anwendungen, die eine niedrige Latenz und einen hohen Durchsatz in großem Umfang erfordern, wie z. B. die semantische Online-Suche.

Skalierungsmodus: Optimiert für Anwendungen mit weniger strengen Latenzvorgaben, wie z. B. RAG und semantische Offline-Suche, und ermöglicht gleichzeitig eine kosteneffiziente Erweiterung von Datensätzen auf einen extrem hohen Maßstab.

AISAQ-Leistungsmodus

AISAQ-Performance erreicht einen "DRAM-Footprint nahe Null", indem PQ-Daten vom Speicher auf die Festplatte verlagert werden, während die IOPS durch Daten-Colocation und Redundanz niedrig gehalten werden.

  • Der Rohvektor eines jeden Knotens, die Kantenliste und die PQ-Daten seiner Nachbarn werden zusammen auf der Festplatte gespeichert.

  • Dieses Layout stellt sicher, dass der Besuch eines Knotens (z. B. Vektor 0) nur eine einzige Festplatten-E/A erfordert.

  • Da die PQ-Daten in der Nähe mehrerer Knoten redundant gespeichert werden, erhöht sich die Größe der Indexdatei beträchtlich, so dass mehr Speicherplatz benötigt wird.

AISAQ-Skala-Modus

AISAQ-scale konzentriert sich auf die Reduzierung des Speicherplatzbedarfs bei gleichzeitiger Erfüllung der Leistungsanforderungen der Zielanwendungen.

In diesem Modus:

  • Die PQ-Daten werden separat auf der Festplatte gespeichert, ohne Redundanz.

  • Dieses Design minimiert die Indexgröße, führt aber zu mehr E/A-Operationen während der Durchquerung des Graphen.

  • Um den IOPS-Overhead zu mindern, führt AISAQ zwei Optimierungen ein:

    • Ein Rearrange-Algorithmus, der die PQ-Vektoren nach Priorität sortiert, um die Datenlokalität zu verbessern.

    • Ein PQ-Cache im DRAM (pq_read_page_cache_size), der häufig genutzte PQ-Daten zwischenspeichert.

Beispielhafte Konfiguration

# milvus.yaml
knowhere:
  AISAQ:
    build:
      max_degree: 56 # Controls the maximum number of connections (edges) each data point can have in the Vamana graph
      search_list_size: 100 # During index construction, this parameter defines the size of the candidate pool used when searching for the nearest neighbors for each node. For every node being added to the graph, the algorithm maintains a list of the search_list_size best candidates found so far. The search for neighbors stops when this list can no longer be improved. From this final candidate pool, the top max_degree nodes are selected to form the final edges
      inline_pq: -1 # Number of PQ vectors stored inline per Index node (read when node is accessed, to reduce IO)
      rearrange: true # Re-arrange the PQ vectors data structure to improve data locality and reduce disk accesses during search (ignored in performance mode)
      num_entry_points: 100 # Number of candidate entry points to optimize search entry-point selection
      pq_code_budget_gb_ratio: 0.125 # Controls the size of the PQ codes (compressed representations of data points) compared to the size of the uncompressed data
      disk_pq_code_budget_gb_ratio: 0.25 # Controls the size of the PQ codes of the high precision vectors stored in the index (used for re-ranking), compared to the size of the uncompressed data
      pq_cache_size: 0 # PQ vectors cache size in DRAM (bytes). The PQ vectors cache is loaded during Index load and used during search to reduce IOs (ignored in performance mode)
      search_cache_budget_gb_ratio: 0 # Controls the amount of DRAM to be used for caching frequently accessed index nodes. This cache is loaded during index load and used during search to reduce IOs
    search:
      search_list: 16 # During a search operation, this parameter determines the size of the candidate pool that the algorithm maintains as it traverses the graph. A larger value increases the chances of finding the true nearest neighbors (higher recall) but also increases search latency
      beamwidth: 8 # Controls the degree of parallelism during search by determining the maximum number of parallel disk I/O requests to read the index nodes
      vectors_beamwidth: 1 # Controls the degree of parallelism during search by determining the maximum number of parallel disk I/O requests to read groups of neighboring PQ vectors (ignored in performance mode)
      pq_read_page_cache_size: 5242880 (5MiB) # PQ read cache size in DRAM per search thread (bytes). It caches frequently accessed data pages containing PQ vectors (ignored in performance mode and applicable only when rearrange is true). The PQ read cache memory is reused across all AISAQ segments

AISAQ-Parameter

AISAQ erbt einige Parameter von DISKANN - max_degree, search_list_size und pq_code_budget_gb_ratio.

Parameter für die Indexerstellung

Diese Parameter beeinflussen, wie der AISAQ-Index aufgebaut wird. Eine Anpassung dieser Parameter kann die Indexgröße, die Aufbauzeit und die Suchqualität beeinflussen.

Parameter

Beschreibung

Wertebereich

Tuning-Vorschlag

max_degree

Steuert die maximale Anzahl von Verbindungen (Kanten), die jeder Datenpunkt im Vamana-Diagramm haben kann.

Typ: Integer

Bereich: [1, 512]

Standardwert: 56

Höhere Werte führen zu dichteren Diagrammen, was die Wiederauffindbarkeit erhöht (es werden mehr relevante Ergebnisse gefunden), aber auch den Speicherverbrauch und die Erstellungszeit erhöht. In den meisten Fällen wird empfohlen, einen Wert innerhalb dieses Bereichs zu wählen: [10, 100].

search_list_size

Während der Indexerstellung definiert dieser Parameter die Größe des Kandidatenpools, der bei der Suche nach den nächsten Nachbarn für jeden Knoten verwendet wird. Für jeden Knoten, der dem Graphen hinzugefügt wird, führt der Algorithmus eine Liste der bisher gefundenen besten Kandidaten in der Größe search_list_size. Die Suche nach Nachbarn endet, wenn diese Liste nicht mehr verbessert werden kann. Aus diesem endgültigen Kandidatenpool werden die Knoten mit dem höchsten Grad ausgewählt, um die endgültigen Kanten zu bilden.

Typ: Integer

Bereich: [1, 512]

Standardwert: 100

Eine größere search_list_size erhöht die Wahrscheinlichkeit, die wahren nächsten Nachbarn für jeden Knoten zu finden, was zu einem qualitativ hochwertigeren Graphen und einer besseren Suchleistung (recall) führen kann. Dies geht jedoch auf Kosten einer deutlich längeren Indexerstellungszeit. Er sollte immer auf einen Wert größer oder gleich max_degree gesetzt werden.

inline_pq

Anzahl der PQ-Vektoren, die pro Index-Knoten inline gespeichert werden (wird beim Zugriff auf den Knoten gelesen, um den IO-Aufwand zu verringern)

Typ: Integer

Bereich: [0, max_degree]

Standardwert: -1

Höhere Werte von inline_pq verbessern die Leistung, erhöhen aber den Speicherplatz.

Setzen Sie inline_pq=0 für AISAQ im Skalierungsmodus.

Setzen Sie inline_pq=-1, um ungenutzten Platz im Index automatisch mit PQ-Vektoren zu füllen, um AISAQ im Skalierungsmodus weiter zu optimieren.

Setzen Sie inline_pq=max_degree für AISAQ im Leistungsmodus.

inline_pq Einstellungen zwischen 0 und max_degree ermöglichen ein einstellbares Gleichgewicht zwischen Leistung und Speicherplatzverbrauch.

rearrange

Ordnen Sie die Datenstruktur der PQ-Vektoren neu an, um die Datenlokalität zu verbessern und die Festplattenzugriffe während der Suche zu reduzieren (im Leistungsmodus ignoriert).

Typ: Boolean

Bereich: [true, false]

Standardwert: true

Wenn true, werden die IOs während der Suche reduziert, wobei der Speicherbedarf und die Zeit für den Indexaufbau nur geringfügig erhöht werden.

num_entry_points

Anzahl der Kandidaten-Einstiegspunkte, um die Auswahl der Such-Einstiegspunkte zu optimieren.

Typ: Integer

Bereich: [0, 1000]

Standardwert: 100

Hohe Werte können die Suchzeit verringern, indem die Suche von einem näheren Einstiegspunkt aus gestartet wird.

Setzen Sie höhere Werte für große Segmente (z. B. für 10M-Vektoren und darüber verwenden Sie einen Wert von 1000).

pq_code_budget_gb_ratio

Steuert die Größe der PQ-Codes (komprimierte Darstellungen der Datenpunkte) im Vergleich zur Größe der unkomprimierten Daten.

Typ: Fließkomma

Bereich: (0.0, 0.25]

Standardwert: 0.125

Ein höheres Verhältnis führt zu genaueren Suchergebnissen, da mehr Informationen über die ursprünglichen Vektoren gespeichert werden, erhöht aber den Rechenaufwand bei der Suche.

In den meisten Fällen wird empfohlen, einen Wert innerhalb dieses Bereichs zu wählen: (0.0417, 0.25].

disk_pq_code_budget_gb_ratio

Steuert die Größe der PQ-Codes der im Index gespeicherten hochpräzisen Vektoren (die für die Neuordnung verwendet werden) im Vergleich zur Größe der unkomprimierten Daten.

Typ: Fließkomma

Bereich: [0, 0.25]

Standardwert: 0.25

Mit dem Standardwert 0,25 werden die Vektoren auf 25 % ihrer ursprünglichen Größe quantisiert (4fache Komprimierung), wodurch der Speicherplatz auf der Festplatte bei relativ geringen Auswirkungen auf die Genauigkeit reduziert wird.

Setzen Sie den Wert 0, um Vektoren mit voller Genauigkeit im Festplattenindex zu speichern und neu zu ordnen. Ein größerer Wert bietet eine höhere Wiederfindungsrate, erhöht aber die Festplattennutzung.

pq_cache_size

Größe des PQ-Vektoren-Caches in DRAM (Bytes). Der PQ-Vektoren-Cache wird beim Laden des Index geladen und während der Suche verwendet, um IOs zu reduzieren (im Leistungsmodus ignoriert).

Typ: Integer

Bereich: [0, 1073741824]

Standardwert: 0

Ein größerer Cache verbessert die Abfrageleistung, erhöht aber die DRAM-Nutzung.

search_cache_budget_gb_ratio

Steuert die Menge an DRAM, die für die Zwischenspeicherung von Indexknoten mit häufigem Zugriff verwendet wird.

Dieser Cache wird beim Laden des Index geladen und während der Suche verwendet, um IOs zu reduzieren.

Typ: Fließkomma

Bereich: [0.0, 0.3)

Standardwert: 0

Ein höherer Wert weist mehr Speicher für die Zwischenspeicherung zu, wodurch weniger Festplattenzugriffe erforderlich sind, aber mehr Systemspeicher verbraucht wird. Ein niedrigerer Wert verwendet weniger Speicher für die Zwischenspeicherung und erhöht möglicherweise den Bedarf an Festplattenzugriffen.

Index-Such-Parameter

Diese Parameter beeinflussen, wie AISAQ die Suche durchführt. Ihre Anpassung kann sich auf die Suchgeschwindigkeit, die Latenzzeit und die Ressourcennutzung auswirken.

Parameter

Beschreibung

Wertebereich

Tuning-Vorschlag

search_list

Während eines Suchvorgangs bestimmt dieser Parameter die Größe des Kandidatenpools, den der Algorithmus beim Durchlaufen des Graphen beibehält. Ein größerer Wert erhöht die Chancen, die wahren nächsten Nachbarn zu finden (höherer Recall), erhöht aber auch die Suchlatenz.

Typ: Integer

Bereich: [topk, int32_max]

Standardwert: 16

Um ein gutes Gleichgewicht zwischen Leistung und Genauigkeit zu erreichen, wird empfohlen, diesen Wert gleich oder etwas größer als die Anzahl der abzurufenden Ergebnisse (top_k) zu setzen.

beamwidth

Steuert den Grad der Parallelität während der Suche, indem die maximale Anzahl der parallelen Festplatten-E/A-Anforderungen zum Lesen der Indexknoten festgelegt wird.

Typ: Integer

Bereich: [1, 16]

Standardwert: 8

Höhere Werte erhöhen die Parallelität, was die Suche auf Systemen mit leistungsstarken CPUs und SSDs beschleunigen kann. Ein zu hoher Wert kann jedoch zu einer übermäßigen Beanspruchung der Ressourcen führen.

In den meisten Fällen empfehlen wir einen Wert von 2.

vectors_beamwidth

Steuert den Grad der Parallelität während der Suche, indem die maximale Anzahl der parallelen Festplatten-E/A-Anforderungen zum Lesen von Gruppen benachbarter PQ-Vektoren festgelegt wird (wird im Leistungsmodus ignoriert).

Typ: Integer

Bereich: [1, 4] muss <= beamwidth sein

Standardwert: 1

Höhere Werte erhöhen die Parallelität, was die Suche auf Systemen mit leistungsstarken CPUs und SSDs beschleunigen kann. Ein zu hoher Wert kann jedoch zu einer übermäßigen Ressourcenkonkurrenz führen, da jede benachbarte PQ-Vektorgruppe bis zu max_degree Vektoren enthalten kann.

In den meisten Fällen wird empfohlen, einen Wert von 1 zu wählen.

pq_read_page_cache_size

PQ-Lese-Cache-Größe in DRAM pro Such-Thread (Bytes). Hier werden häufig aufgerufene Datenseiten, die PQ-Vektoren enthalten, zwischengespeichert (im Leistungsmodus ignoriert und nur anwendbar, wenn rearrange true ist).

Der PQ-Lese-Cache-Speicher wird für alle AISAQ-Segmente wiederverwendet.

Typ: Integer

Bereich: [0, 33554432]

Standardwert: 5242880 (5MiB)

Ein größerer Cache verbessert die Abfrageleistung, erhöht aber den DRAM-Verbrauch.

Empfohlene Werte reichen von 2 MiB für kleine Segmente (1 M Vektoren), 5 MiB für mittlere Segmente (50 M Vektoren) und 10 MiB für große Segmente (250 M Vektoren).