Filter in Vektorabfragen

Sie können Vektorfiltermodi für eine Vektorabfrage festlegen, um anzugeben, ob die Filterung vor oder nach der Abfrageausführung erfolgen soll.

Filter bestimmen den Bereich einer Vektorabfrage. Filter werden festgelegt und über nicht Vektorzeichenfolgen und numerische Felder durchlaufen, die als filterable im Index zugeschrieben werden, aber der Zweck eines Filters bestimmt, was die Vektorabfrage ausgeführt wird: den gesamten durchsuchbaren Bereich oder den Inhalt eines Suchergebnisses.

In diesem Artikel werden die einzelnen Filtermodi beschrieben und Anleitungen zu ihrer Verwendung bereitgestellt.

Vorfiltermodus

Bei der Vorfilterung wird der Filter vor der Abfrageausführung angewendet. Dadurch wird der Suchbereich verkleinert, in dem der Algorithmus für die Vektorsuche nach ähnlichen Inhalten sucht. In einer Vektorabfrage ist preFilter die Standardeinstellung.

Diagram of prefilters.

Nachfiltermodus

Bei der Nachfilterung werden Filter nach der Abfrageausführung angewendet, um die Suchergebnisse einzugrenzen.

Diagram of post-filters.

Benchmarktests für Vektorfiltermodi

Um die Bedingungen zu verstehen, unter denen ein Filtermodus besser funktioniert als der andere, haben wir eine Reihe von Tests durchgeführt, um Abfrageergebnisse für kleine, mittlere und große Indizes auszuwerten.

  • Klein (100.000 Dokumente, 2,5 GB Index, 1.536 Dimensionen)
  • Mittel (1 Mio. Dokumente, 25 GB Index, 1.536 Dimensionen)
  • Groß (1 Mrd. Dokumente, 1,9 TB Index, 96 Dimensionen)

Für die kleinen und mittleren Workloads haben wir einen S2-Dienst (Standard 2) mit einer einzelnen Partition und einem einzelnen Replikat verwendet. Für die große Workload haben wir einen S3-Dienst (Standard 3) mit 12 Partitionen und einem einzelnen Replikat verwendet.

Die Indizes waren gleich aufgebaut und umfassten ein Schlüsselfeld, ein Vektorfeld, ein Textfeld und ein numerisches filterbares Feld. Der folgende Index wird mithilfe der Syntax 2023-07-01-Vorschau definiert.

def get_index_schema(self, index_name, dimensions):
    return {
        "name": index_name,
        "fields": [
            {"name": "id", "type": "Edm.String", "key": True, "searchable": True},
            {"name": "content_vector", "type": "Collection(Edm.Single)", "dimensions": dimensions,
              "searchable": True, "retrievable": True, "filterable": False, "facetable": False, "sortable": False,
              "vectorSearchConfiguration": "defaulthnsw"},
            {"name": "text", "type": "Edm.String", "searchable": True, "filterable": False, "retrievable": True,
              "sortable": False, "facetable": False},
            {"name": "score", "type": "Edm.Double", "searchable": False, "filterable": True,
              "retrievable": True, "sortable": True, "facetable": True}
        ],
        "vectorSearch":
        {
            "algorithmConfigurations": [
                {"name": "defaulthnsw", "kind": "hnsw", "hnswParameters": {"metric": "euclidean"}}
            ]
        }
    }

In Abfragen wurde sowohl für Vorfilter- als auch für Nachfiltervorgänge ein identischer Filter verwendet. Wir haben einen einfachen Filter verwendet, um sicherzustellen, dass Leistungsabweichungen auf den Modus und nicht auf die Komplexität des Filters zurückzuführen sind.

Die Ergebnisse wurden in Abfragen pro Sekunde (Queries Per Second, QPS) gemessen.

Wesentliche Punkte

  • Die Vorfilterung ist fast immer langsamer als die Nachfilterung (außer bei kleinen Indizes, wo die Leistung ungefähr gleich bleibt).

  • Bei größeren Datasets ist die Vorfilterung erheblich langsamer.

  • Warum also wird als Standard die Vorfilterung verwendet, wenn sie fast immer langsamer ist? Die Vorfilterung sorgt dafür, dass k Ergebnisse zurückgegeben werden, wenn sie im Index vorhanden sind. Dabei haben Abruf und Genauigkeit Vorrang vor Geschwindigkeit.

  • Die Nachfilterung ist für Kunden gedacht, für die Folgendes gilt:

    • Sie legen mehr Wert auf Geschwindigkeit als auf die Auswahl. (Bei der Nachfilterung können weniger als k Ergebnisse zurückgeben werden.)
    • Sie verwenden Filter, die nicht allzu selektiv sind.
    • Sie verfügen über Indizes mit einer Größe, die zu einer nicht akzeptablen Vorfilterleistung führt.

Details

  • Bei einem Dataset mit 100.000 Vektoren und 1.536 Dimensionen wurden folgende Ergebnisse ermittelt:

    • Bei der Filterung von mehr als 30 Prozent des Datasets waren Vor- und Nachfilterung vergleichbar.
    • Bei der Filterung von weniger als 0,1 Prozent des Datasets war die Vorfilterung etwa 50 Prozent langsamer als die Nachfilterung.
  • Bei einem Dataset mit 1 Mio. Vektoren und 1.536 Dimensionen wurden folgende Ergebnisse ermittelt:

    • Bei der Filterung von mehr als 30 Prozent des Datasets war die Vorfilterung ca. 30 Prozent langsamer.
    • Bei der Filterung von weniger als zwei Prozent des Datasets war die Vorfilterung ca. sieben Mal langsamer.
  • Bei einem Dataset mit 1 Mrd. Vektoren und 96 Dimensionen wurden folgende Ergebnisse ermittelt:

    • Bei der Filterung von mehr als fünf Prozent des Datasets war die Vorfilterung ca. 50 Prozent langsamer.
    • Bei der Filterung von weniger als zehn Prozent des Datasets war die Vorfilterung ca. sieben Mal langsamer.

Die folgende Abbildung zeigt die relativen QPS der Vorfilterung (Vorfilter-QPS dividiert durch Nachfilter-QPS).

Chart showing QPS performance for small, medium, and large indexes for relative QPS.

Die vertikale Achse stellt die QPS der Vorfilterung den QPS der Nachfilterung gegenüber. Der Wert 0,0 bedeutet beispielsweise, dass die Vorfilterung 100 Prozent langsamer ist. 0,5 auf der vertikalen Achse bedeutet, dass die Vorfilterung 50 Prozent langsamer ist, und 1,0 bedeutet, dass Vor- und Nachfilterung gleich sind.

Die horizontale Achse stellt die Filterrate oder den Prozentsatz der Kandidatendokumente nach Anwendung des Filters dar. 1.00% bedeutet beispielsweise, dass durch die Filterkriterien ein Prozent des Suchkorpus ausgewählt wurde.