Jede Datensammlung ist in Segmente unterteilt. Jedes Segment verfügt über unabhängige Vektor-Speicherung, Nutzlast-Speicherung und Indexierung.
Die Daten in den Segmenten überlappen normalerweise nicht. Allerdings führt das Speichern desselben Punktes in verschiedenen Segmenten nicht zu Problemen, da die Suche einen Deduplizierungsmechanismus enthält.
Die Segmente umfassen Vektor-Speicherung, Nutzlast-Speicherung, Vektor-Index, Nutzlast-Index und einen ID-Mapper zur Speicherung der Beziehung zwischen internen und externen IDs.
Die Segmente können je nach Art der Speicherung und Indexierung "anfügbare" oder "nicht-anfügbare" sein. In "anfügbaren" Segmenten können Daten frei hinzugefügt, gelöscht und abgefragt werden, während in "nicht-anfügbaren" Segmenten nur Daten gelesen und gelöscht werden können.
Die Konfiguration der Segmente in einer Sammlung kann unterschiedlich und unabhängig voneinander sein, allerdings ist mindestens ein "anfügbarer" Segment erforderlich.
Vektor-Speicherung
Je nach den Anforderungen der Anwendung kann Qdrant eine der folgenden Datenspeicherungsoptionen verwenden. Die Auswahl muss ein Gleichgewicht zwischen der Suchgeschwindigkeit und dem RAM-Verbrauch herstellen.
Speicherung im Arbeitsspeicher - Speichert alle Vektoren im RAM und bietet die höchste Geschwindigkeit, da nur bei der Persistenz auf den Datenträger zugegriffen werden muss.
Memmap-Speicherung - Erstellt einen virtuellen Adressraum, der mit einer Datei auf dem Datenträger verknüpft ist. Kartierte Dateien werden nicht direkt in den RAM geladen, sondern über die Seitenzwischenspeicherung zugegriffen. Mit ausreichend RAM ist die Geschwindigkeit fast so schnell wie bei der Speicherung im Arbeitsspeicher.
Konfigurieren der Memmap-Speicherung
Es gibt zwei Möglichkeiten, die Verwendung von Memmap (auch als Datenträgerspeicherung bekannt) zu konfigurieren:
- Setzen Sie die Option
on_disk
für Vectoren in der API zur Erstellung der Sammlung:
Nur anwendbar auf v1.2.0 und höher
PUT /collections/{Sammlungsname}
{
"Vektoren": {
"Größe": 768,
"Abstand": "Cosinus",
"on_disk": true
}
}
Damit wird eine Sammlung erstellt, die sofort alle Vektoren in der Memmap-Speicherung speichert. Dies ist der empfohlene Ansatz, wenn die Qdrant-Instanz schnelle Datenträger verwendet und große Sammlungen verarbeiten muss.
- Setzen Sie die Option
memmap_threshold_kb
. Diese Option legt den Schwellenwert für die Umwandlung von Segmenten in Memmap-Speicherung fest.
Es gibt zwei Möglichkeiten, dies umzusetzen:
- Setzen Sie den Schwellenwert global in der Konfigurationsdatei. Der Parametername lautet
memmap_threshold_kb
. - Setzen Sie den Schwellenwert für jede Sammlung individuell während der Erstellung oder Aktualisierung fest.
PUT /collections/{Sammlungsname}
{
"Vektoren": {
"Größe": 768,
"Abstand": "Cosinus"
},
"optimizers_config": {
"memmap_threshold": 20000
}
}
Die Faustregel für die Einstellung des Memmap-Schwellenwertparameters ist einfach:
- Wenn das Anwendungsszenario ausgewogen ist – setzen Sie den Memmap-Schwellenwert auf denselben Wert wie den
indexing_threshold
(Standardwert ist 20000). In diesem Fall führt der Optimierer keine zusätzlichen Durchläufe durch und optimiert alle Schwellenwerte auf einmal. - Wenn die Schreiblast hoch ist und der RAM knapp ist – setzen Sie den Memmap-Schwellenwert niedriger als den
indexing_threshold
, beispielsweise 10000. In diesem Fall wandelt der Optimierer zuerst Segmente in die Memmap-Speicherung um und wendet dann die Indexierung an.
Zusätzlich können Sie die Memmap-Speicherung nicht nur für Vektoren, sondern auch für HNSW-Indizes verwenden. Um diese Funktion zu aktivieren, setzen Sie den Parameter hnsw_config.on_disk
auf true
, wenn Sie die Sammlung erstellen.
PUT /collections/{Sammlungsname}
{
"Vektoren": {
"Größe": 768,
"Abstand": "Cosinus"
},
"optimizers_config": {
"memmap_threshold": 20000
},
"hnsw_config": {
"on_disk": true
}
}
Speicherung von Payloads
Qdrant unterstützt zwei Arten der Payload-Speicherung: InMemory und OnDisk.
Die InMemory-Payload-Speicherung organisiert die Payload-Daten genauso wie Vektoren im Speicher. Die Payload-Daten werden beim Start des Dienstes in den Speicher geladen, während die Festplatte und RocksDB nur für die Persistenz verwendet werden. Diese Art der Speicherung ist sehr schnell, erfordert jedoch möglicherweise einen großen Speicherplatz, insbesondere wenn die Payload große Werte enthält (wie z.B. Textzusammenfassungen oder sogar Bilder).
Für große Payload-Werte ist es ratsam, die OnDisk-Payload-Speicherung zu verwenden. Diese Art der Speicherung liest und schreibt die Payload direkt in RocksDB und erfordert daher keinen großen Speicherplatz. Allerdings ist die Zugriffslatenz ein Nachteil. Wenn Sie Vektoren basierend auf Payload-Bedingungen abfragen müssen, kann das Überprüfen der auf der Festplatte gespeicherten Werte zu lange dauern. In diesem Fall empfehlen wir, für jedes zur Filterung verwendete Feld einen Payload-Index zu erstellen, um den Festplattenzugriff zu vermeiden. Sobald der Feldindex erstellt ist, behält Qdrant immer alle Werte des indizierten Feldes im Speicher, unabhängig von der Art der Payload-Speicherung.
Sie können den gewünschten Payload-Speichertyp über die Konfigurationsdatei oder durch Verwendung des Parameters on_disk_payload
bei der Erstellung einer Sammlung festlegen.
Versionskontrolle
Um die Datenintegrität sicherzustellen, führt Qdrant alle Datenänderungen in zwei Stufen durch. Zunächst werden die Daten im Write-ahead-Log (WAL) geschrieben, das alle Operationen sortiert und fortlaufende Nummern zuweist.
Sobald die Änderungen dem WAL hinzugefügt wurden, gehen sie selbst bei einem Stromausfall nicht verloren. Anschließend gelangen die Änderungen in das Segment. Jedes Segment speichert die neueste Version der darauf angewendeten Änderungen sowie die Version jedes einzelnen Punktes. Wenn die fortlaufende Nummer einer neuen Änderung kleiner ist als die aktuelle Version eines Punktes, ignoriert der Aktualisierer diese Änderung. Dieser Mechanismus ermöglicht es Qdrant, den Speicherplatz effizient aus dem WAL wiederherzustellen, falls es zu einem abnormalen Shutdown kommt.