Vector Search Queries
Nearest Neighbor
SELECT id, vector_distance(embedding, ARRAY[0.1, 0.3, -0.2, ...]) AS dist
FROM articles
ORDER BY dist LIMIT 10;
Returns the 10 nearest neighbors by the metric configured on the index (l2, cosine, inner_product, manhattan, chebyshev, hamming, jaccard, or pearson). The planner detects ORDER BY vector_distance(...) LIMIT k and rewrites it into an ANN top-k plan; no special SEARCH keyword is required.
Filtered Vector Search
SELECT title, vector_distance(embedding, ARRAY[0.1, 0.3, ...]) AS score
FROM articles
WHERE category = 'machine-learning'
ORDER BY score LIMIT 10;
The engine builds a Roaring Bitmap of matching IDs and selects the optimal strategy: pre-filter (selective filters), post-filter (broad filters), or brute-force (very selective).
Distance Function
SELECT id, vector_distance(embedding, $query_vec) AS dist
FROM articles
ORDER BY dist LIMIT 10;
Operator Forms
| Operator | Function | Metric |
<-> | vector_distance | L2 |
<=> | vector_cosine_distance | Cosine |
<#> | vector_neg_inner_product | Negative inner product |
SELECT id FROM articles ORDER BY embedding <=> $query_vec LIMIT 10;
ANN Tuning (Named Arguments)
vector_distance and its cosine / inner-product peers accept named tuning arguments via =>. JSON-string options are not accepted — every option is a typed, closed-set named argument:
SELECT id, vector_distance(
embedding, $query_vec,
quantization => 'rabitq',
oversample => 4,
ef_search => 128,
target_recall => 0.95
) AS dist
FROM articles
ORDER BY dist LIMIT 10;
| Argument | Type | Notes |
quantization | string | none, sq8, pq, binary, ternary, rabitq, bbq, opq |
oversample | u8 | Candidates fetched before re-ranking. Default 3. Final rerank set is oversample × ef_search. |
query_dim | u32 | Coarse-to-fine on first-N dims of Matryoshka embeddings. None = full dimensionality. |
meta_token_budget | u8 | MetaEmbed multivec scoring budget for MaxSim / PLAID |
ef_search | u32 | HNSW / Vamana search-time beam width. Default 64. |
target_recall | f32 | Adaptive recall target. The cost-model planner picks oversample / ef_search to hit this. |
Unknown names, duplicate keys, positional 3rd args, or wrong operators (= instead of =>) all return typed errors that list the canonical names.
Quantization Choice
| Codec | Bits/dim | Recall (typ.) | When to pick it |
none | 32 | 100% | Small index (< 1M vectors), latency not critical |
sq8 | 8 | ~99% | Balanced default for medium index sizes |
pq | ~2 | ~95% | Large memory-bound indexes; classic Product Quantization |
opq | ~2 | ~96% | PQ + learned random rotation; minor accuracy bump over pq |
rabitq | 1 | ~97% | Frontier 1-bit with O(1/√D) error bound (SIGMOD 2024) |
bbq | 1 | ~98% | Centroid-asymmetric 1-bit + 14-byte corrective; oversample-rerank |
binary | 1 | ~85% | Hamming-only, no rerank — for ultra-cold tiers |
ternary | 1.58 | ~96% | BitNet-style {-1, 0, +1} — cold/hot pack for AVX-512 |
The cost-model planner (target_recall) will pick oversample and ef_search automatically once you set the recall target. Manually set those two only when you need a hard latency ceiling.
Index Implementations
You don't pick the underlying index directly — it's chosen by the planner from collection metadata + workload signals:
- HNSW — in-memory hierarchical graph, the default for moderate-size indexes
- Vamana / DiskANN — flat-beam SSD-resident graph for billion-scale on a single node (
Tier 2of the vector frontier) - NaviX adaptive-local filtered traversal (VLDB 2025) — switches per-hop between standard / directed / blind heuristics based on local selectivity. Replaces classic ACORN-1 filtered ANN.
- SIEVE workload-driven subindex collections — the planner builds specialized HNSW subindices for stable predicates (e.g.
tenant_id) and routes filtered queries to them. - MetaEmbed multi-vector + ColBERT MaxSim + PLAID (ICLR 2026) — learnable Meta Tokens replace per-token explosion; budgeted MaxSim at query time via
meta_token_budget. - Matryoshka adaptive-dim querying — coarse-to-fine ranking on the first-N dimensions of MRL embeddings via
query_dim. - SPFresh streaming updates (SOSP 2023) — LIRE topology-aware local rebalancing; no full-rebuild stalls when vectors are added/removed.
Vector-Primary Collections
By default, vectors are an index attached to a column on a normal collection — the document/strict store is the source of truth, and the vector index is a side path. For pure-vector workloads (RAG corpora, recommendation memory, embedding stores) you can flip a collection into vector-primary mode, where the vector index becomes the primary access path and the document store is a metadata sidecar:
CREATE COLLECTION corpus (
id UUID DEFAULT gen_uuid_v7(),
embedding FLOAT[384],
title TEXT,
tenant_id UUID,
created_at TIMESTAMP DEFAULT now()
) WITH (
primary='vector',
vector_field='embedding',
dim=384,
metric='cosine',
quantization='rabitq',
m=32,
ef_construction=200,
payload_indexes=['tenant_id', 'created_at']
);
| Option | Notes |
primary | 'document' (default), 'strict', 'kv', or 'vector' |
vector_field | Required when primary='vector'. Column name of the embedding. |
dim | Required. Embedding dimensionality. |
metric | 'cosine', 'l2', 'inner_product', etc. |
quantization | Storage-level codec (same vocabulary as the query-time arg above). |
m, ef_construction | HNSW build-time parameters. |
payload_indexes | Per-field equality / range / boolean indexes over the metadata sidecar for filtered ANN. Replaces Pinecone metadata filters. |
In vector-primary mode the planner treats the vector index as the source of truth for IDs; metadata fetches only happen for hit IDs. Cross-engine queries, CRDT sync, and SQL semantics all keep working — primary='vector' is purely an access-path hint, not a different engine.
Default primary='document' is unchanged: the existing CREATE VECTOR INDEX ON ... syntax continues to work for vector-as-side-index workloads.
Hybrid Vector + Text (RRF)
SELECT title, rrf_score(
vector_distance(embedding, $query_vec),
bm25_score(body, 'transformer attention')
) AS score
FROM articles
LIMIT 10;
Reciprocal Rank Fusion merges BM25 text results with vector similarity in a single pass.
Multiple vector columns per collection
A collection can carry several vector indexes, one per embedding column — name the column in parentheses after the collection. Each index gets its own metric and parameters; queries pick the column they search:
CREATE VECTOR INDEX idx_text ON products (text_embedding) METRIC cosine DIM 384;
CREATE VECTOR INDEX idx_image ON products (image_embedding) METRIC cosine DIM 512;
-- Search the text-embedding index:
SELECT id FROM products ORDER BY text_embedding <=> $text_vec LIMIT 10;
-- ...or the image-embedding index:
SELECT id FROM products ORDER BY image_embedding <-> $image_vec LIMIT 10;
Omitting (<column>) targets the collection's default (unnamed) vector field — fine when there's only one embedding column (as in the CREATE VECTOR INDEX idx_embed ON articles ... examples above).