Der Mechanismus · 0.1.0b4

Ein Verzeichnis-Lookup.
Ein zusammenhängender Scan.

Gefilterter Vektorsuche ist meist ein Scatter-Gather über einen Index, der nichts über Ihren Filter weiß. Telys besitzt stattdessen das physische Layout: beim Partitionsschlüssel ist nächste-Nachbarn-wo-Schlüssel-gleich-x ein O(1)-Verzeichnis-Lookup plus ein sequenzieller Scan eines zusammenhängenden Blocks. Diese Seite beschreibt die heute ausgelieferte Runtime und anschließend die Architektur, auf die sie zusteuert — als Spec gekennzeichnet.

Panel 01 · Heute — die ausgelieferte Runtime
01 Physisches Layout

Die Engine bestimmt, wo jeder Vektor liegt.

Eine Collection deklariert partition_by bei der Erstellung, und das Layout folgt dem Schlüssel. Das Basissegment ist nach Partition geclustert — jeder Schlüssel wird auf einen zusammenhängenden Slice abgebildet — und aktuelle Schreibvorgänge liegen daneben in einem veränderbaren, Arrow-förmigen Delta.

Basissegment

Partitions-geclustert

Vektoren werden nach Partitionsschlüssel sortiert gespeichert, sodass jede Partition ein zusammenhängender Block ist. Eine bereichsbegrenzte Abfrage liest einen einzigen sequenziellen Speicherbereich, keine über einen Index verteilten Zeilen.

Partitionsverzeichnis

O(1) key → slice

Ein Verzeichnis ordnet jedem Partitionswert sein (offset, length) im Basissegment zu. Das Auflösen des Filters ist ein Dictionary-Lookup, keine Index-Traversierung.

Veränderbares Delta

Arrow-förmige Schreibvorgänge

add und upsert hängen hier an, jede Zeile mit einem monotonen Schreib-LSN gestempelt. Das Delta ist sofort abfragbar und wird über einen einzigen Scan-Pfad mit dem Basis-Slice vereinigt.

02 Der Lesepfad

Was eine bereichsbegrenzte Abfrage ausführt.

Abfrage

col.search(qvec, where={"tenant_id": "acme"}, top_k=10)

Der Filter benennt den Partitionsschlüssel, mit dem die Collection erstellt wurde.

Partitionsverzeichnis

O(1)-Lookup: der Partitionswert wird auf (offset, length) im Basissegment aufgelöst. Keine Kandidatengenerierung, kein Graph-Einstiegspunkt.

Zusammenhängender Slice-Scan

SIMD-exaktes Scoring über einen einzigen sequenziellen Block. Recall auf diesem Pfad ist 1,0 — es ist ein Scan, keine Approximation. Gemessene p50/p95 für diesen Schritt werden auf der Benchmarks-Seite veröffentlicht, jeweils gebunden an ihr Recall-Gate und ihr System.

Delta-Union

Zeilen mit demselben Schlüssel im Arrow-förmigen Delta werden über denselben Pfad bewertet. Ein Schreibvorgang ist für die unmittelbar folgende Abfrage sichtbar.

MVCC-Sichtbarkeit

Treffer werden am Snapshot-LSN gefiltert: tombstoned und verdrängte Versionen tauchen nie auf. Top-k wird mit dem explain-Payload zurückgegeben.

Überdimensionierte Partitionen nehmen einen deklarierten Fork: build_ivf legt einen partitionsweisen IVF über jede Partition oberhalb des Zeilenschwellenwerts, und Abfragen werden mit einem exakten Rerank darüber geroutet — kalibriert gegen einen Recall-Floor und im Plan benannt.

03 Der explain-Fork

Jedes Ergebnis benennt seinen Plan.

explain=True gibt den physischen Plan zurück, den die Abfrage tatsächlich genommen hat. Beim Partitionsschlüssel erhält man den zusammenhängenden Slice-Scan. Überdimensionierte Partitionen deklarieren den IVF-Fork. Filter außerhalb des Schlüssels fallen auf Scatter-Gather zurück — und der Payload erklärt warum.

explain
hits = col.search(qvec, where={"tenant_id": "acme"}, top_k=10, explain=True)

hits["explain"]["plan"]
# on the partition key  → "PartitionSliceExactF32"   # one contiguous slice, exact, recall 1.0
# oversized partition   → "PartitionIVFRerankF32"   # per-partition IVF + exact rerank
# off-key filter        → "ScatterGatherExact"      # fallback — and it says why:

hits["explain"]["fallback_reason"]
# "path is not the physical partition key"
04 Schreibvorgänge und Zeit

Nichts wird überschrieben. Versionen werden verdrängt.

Das Schreibmodell ist append-only MVCC. upsert schreibt eine neue Version einer logischen ID und markiert die vorherige als verdrängt; delete setzt einen Tombstone an einem Delete-LSN; snapshot() fixiert eine konsistente Leseansicht; compact() faltet das Delta in die Basis und verwirft, was kein Snapshot mehr sehen kann.

python
col.upsert(vectors, ids=ids, metadata=metadata)   # a new version; the prior one is superseded
col.delete(["doc-41"])                            # tombstone at a delete LSN — no in-place erase
lsn = col.snapshot()                              # pin a consistent read view at an LSN
col.compact()                                     # fold delta into base; drop superseded rows
col.build_ivf(min_rows=20000, target_recall=0.98)
AufrufFunktion
hinzufügen / add_textsNeue Zeilen einfügen. Doppelte IDs werden abgelehnt — eine zweite physische Zeile für eine logische ID erfordert bewusst upsert.
einfügen/aktualisieren / upsert_textsEine neue Version einer logischen ID schreiben; die vorherige Version wird verdrängt, nie direkt überschrieben.
suchen / search_textGefiltertes Top-k. explain=True hängt den physischen Plan an das Ergebnis.
deleteLogische Zeilen an einem Delete-LSN mit einem Tombstone versehen.
compactDas Delta in das Basissegment falten; tombstoned und verdrängte Versionen verwerfen.
build_ivfPartitionsweisen IVF über Partitionen oberhalb des Zeilenschwellenwerts aufbauen, kalibriert auf einen Recall-Floor.
snapshotEinen LSN zurückgeben, der eine konsistente Leseansicht fixiert.
save / statsDie Collection auf Disk persistieren; Zeilenzahlen, Partitionen und Layout-Fakten ausgeben.
Panel 02 · Richtung — die Architektur-Spec

Alles Folgende ist Spezifikation, keine ausgelieferte API-Referenz. Es ist das Substrat, auf das die Runtime hinkonvergiert. Die SDK-seitige Naht ist eingefroren, sodass der Austausch darunter für Aufrufer unsichtbar bleibt.

05 Das Zielsubstrat

Ein Planner. Ein flaches IR. Ein Executor.

Drei Front-Ends werden in einen Planner abgesenkt, der eine flache physische Zwischendarstellung ausgibt, die von einem Mojo-vektorisierten Executor direkt über Arrow-Buffern ausgeführt wird.

Front-Ends

Das Speichermodell (remember · recall · as_of), die Abfrage-API (point_get · scan · search · hybrid_search) und das Fabric. Ein einziger Eingangsvertrag; kein API-spezifischer Engine.

Ein Planner

Logische und physische Planung an einem Ort. Selektivität wird aus Segmentstatistiken geschätzt; der Plan ist explizit und wird mit dem Ergebnis zurückgegeben.

Ein flaches IR

Ein flaches Array von Operatoren, gebunden durch Integer-Slots. Das Inter-Operator-Register ist ein Row-Set — eine Bitmap, sortierte Row-IDs oder ein Selektionsvektor.

Ein Mojo-Executor

Vektorisierte Ausführung über Arrow-Buffern und FAISS-Kandidaten-Arrays. Der SIMD-Hot-Path bleibt außerhalb von Python; komprimierte Parquet-Seiten werden zuerst in Scratch-Buffer dekodiert.

Arrow-Delta + WAL

Die Mutations-Schicht

Ein Write-Ahead-Log für Dauerhaftigkeit und Ordnung sowie ein veränderbares Arrow-förmiges Delta für sofortige Sichtbarkeit — die Tabellenschicht, die Parquet allein fehlt.

Parquet-Segmente

Versiegelt, unveränderlich

Dauerhaft komprimierte Spaltensegmente. Footer-Statistiken steuern Segment- und Row-Group-Pruning; versiegelte Dateien werden nie verändert.

.vidx-Sidecars

FAISS ANN

Segmentweise FAISS-Indizes, an Prüfsumme und Version des Segments gebunden, read-only gemappt mit einer Lebensdauer, die an den Lese-Snapshot gekoppelt ist.

Scalar + Sparse-Sidecars

Pruning und Lexik

Zone-Maps, Bloom-Filter und Bitmaps für Pruning; ein BM25-Sidecar für Sparse-Retrieval und Score-Fusion.

flaches IR — Operator-Set
SCAN  FILTER  PROJECT  POINT_GET  RANGE_GET  AGGREGATE  TOP_K
HASH_JOIN  HASH_GROUP_BY  SORT
ANN_SEARCH  SPARSE_SEARCH  FUSE  RERANK  MATERIALIZE
06 Der Schreibpfad

WAL zuerst. Sofort sichtbar. Im Hintergrund versiegelt.

WAL-Append

Append-only-Frames mit Prüfsummen und monotonen LSNs. Die Wiederherstellung spielt Datensätze nach dem letzten versiegelten LSN erneut ab und bricht bei der ersten fehlerhaften Prüfsumme ab.

Arrow-Delta

Der Schreibvorgang landet im veränderbaren Delta und ist sofort abfragbar — versiegelte Segmente und Delta vereinigen sich über einen einzigen Scan-Pfad.

Hintergrundversiegelung

Ab einem Schwellenwert für Größe, Zeilenanzahl oder Alter wird das Delta sortiert und als Parquet-Segment mit zugehöriger .vidx und Sidecars geschrieben, dann per atomarem Manifest-Swap veröffentlicht.

Compaction

Hintergrund-Merges fassen kleine Segmente zusammen, entfernen tombstoned Rows und bauen Sidecars neu auf — budgetgesteuert, damit On-Device-Deployments ruhig bleiben.

Versiegelte Segmente werden nie verändert. Ein Lesevorgang pinnt (Manifest-Snapshot, LSN); Writer versiegeln neue Segmente und tauschen das Manifest, ohne laufende Lesevorgänge zu stören. Die Garbage Collection wartet auf den ältesten aktiven Snapshot.

07 Gefiltertes ANN als Planung

Der Filter wählt den Plan — nicht umgekehrt.

Gefiltertes ANN ist adaptive Planung nach Selektivität: Der Planner schätzt anhand von Segmentstatistiken, wie viele Rows den Filter überleben, und wählt dann die günstigste Strategie, die den Recall-Vertrag einhält.

Selektiv

Vorfilter → exakt

Zuerst skalarer oder Bitmap-Prefilter, dann exaktes SIMD-Scoring über die verbleibenden Rows. Unterhalb eines Zeilenschwellenwerts wird ANN vollständig übersprungen — exakter Scan, Recall 1,0.

Moderat

Allow-Bitmap-Traversal

Die ANN-Traversierung trägt ein Allow-Bitmap, sodass der Index nur Rows liefert, die der Filter zulässt.

Breit

ANN → Nachfilter

Zuerst ANN mit adaptivem Over-Fetch, dann Post-Filter. Der Filter entfernt wenig, daher führt die Kandidatengenerierung.

08 Status

Korrektheitsprüfungen gehen jeder Geschwindigkeitszahl voraus.

Die ausgelieferte Runtime wird durch Paritäts-Suites verifiziert, die gegen beide Engine-Implementierungen laufen, und jede Abfrage kann den physischen Plan benennen, den sie genommen hat. Das ist die Reihenfolge hier: zuerst Korrektheitsprüfungen, dann Messung.

Benchmarks werden unter einem Fairness-Vertrag veröffentlicht — angeglichener Recall, angeglichene Hardware, transport-separierte Ergebnisse, Sieg / Unentschieden / Niederlage ausgewiesen. Die ersten gemessenen Ergebnisse sind jetzt live auf der Benchmarks-Seite — jede Zahl mit ihren vollständigen Bedingungen: Hardware, Datensatz, Dimension, Selektivität, Recall und Transport. Jeder Multiplikator bleibt eine Hypothese außerhalb der angegebenen Bedingungen.

Benchmark-Methodik lesenProduktoberfläche ansehen