Skip to main content

Brute-force kNN

UDTF: cuvs_brute_force_knn

Official cuVS reference: C API

Exact brute-force nearest-neighbor search over dense vectors.

Quickstart​

The call below expects the registered relations dataset_vectors (the dataset role) and query_vectors (the queries role), each passed as a parenthesized SELECT subquery.

SELECT *
FROM cuvs_brute_force_knn(
dataset => (SELECT id, d0, d1 FROM dataset_vectors),
queries => (SELECT id, d0, d1 FROM query_vectors),
k => 8,
metric => 'l2_expanded'
);

Inputs​

Each relation argument is a parenthesized SELECT subquery that the planner keeps as an operator child. Metadata validation resolves a registered table or view for the same role. See Vector Inputs for the relation identity rules and the ID, dense-vector type, null, finite-value, and runtime-dimension contract.

RoleRequiredValidation referenceDescription
datasetyestableDense-vector rows indexed for nearest-neighbor search.
queriesyestableDense-vector query rows matched against the evaluated dataset.

Vector element types​

Element typeValid metrics
Float32l2_expanded, l2_sqrt_expanded, cosine, inner_product

Arguments and options​

Scalar SQL arguments​

ArgumentTypeRequiredDefaultConstraintsDescription
kintegeryesNo defaultminimum 1; maximum 4294967295Number of neighbors returned for each evaluated query row.
metricstringyesNo defaultone of "l2_expanded", "l2_sqrt_expanded", "cosine", "inner_product"Distance or score metric. Distance metrics rank lower values first; inner product ranks higher values first.

Vector binding shapes​

Each relation subquery must project an id field followed by either one or more feature fields of a supported element type (Float32) or one list field of a supported element type, under any name.

For wide vectors, the projection order defines the feature dimensions. A list vector relation must contain no feature field beside id and its list field. Nullable field types are accepted. A null ID, feature value, list row, or list element fails the query.

Output​

ColumnTypeNullableDescription
query_ordinalUInt64noZero-based ordinal of the evaluated query row; it disambiguates duplicate query IDs.
query_idsame_as_queries.idnoLogical ID copied from the queries relation.
neighbor_ordinalUInt64noZero-based ordinal of the matched dataset row; it disambiguates duplicate dataset IDs.
neighbor_idsame_as_dataset.idnoLogical ID copied from the matched dataset row.
rankUInt32noOne-based neighbor rank within a query. Order consumers explicitly by query_ordinal, rank.
distanceFloat32noMetric value; smaller is better for distance metrics, while inner_product prefers larger values.

The output schema depends on the call. Run gpu_validate_call against registered relations to inspect the schema that the validated ID types and literal options produce.

Examples​

Does a Pokemon lookalike audience find new interest?​

The lookalike list contains shoppers whose taste vectors resemble earlier Pokemon buyers. The query checks whether they later bought Pokemon and whether they had already viewed it, against the simple rule of selecting previous Pokemon viewers.

Earlier CTEs construct 64 category-preference features from views before September 1, 2023. Each value is the square root of a shopper's share of views in one of the 64 busiest categories. Eligibility requires 20 views. The seed contains 1,302 eligible July to August Pokemon buyers; candidates excludes them.

The unfolded part of the SQL searches for 20 neighbors per seed buyer, deduplicates the list, splits it by prior Pokemon views and joins September to October purchases. The folded relations build the features in the same query.

), lookalikes AS (
SELECT DISTINCT neighbor_id AS id
FROM cuvs_brute_force_knn(
dataset => (SELECT * FROM candidates ORDER BY id),
queries => (SELECT t.* FROM taste t JOIN seed s ON s.id = t.id ORDER BY t.id),
k => 20, metric => 'l2_expanded')
), pokemon_viewers AS (
SELECT DISTINCT user_id AS id FROM views WHERE brand_id = 17470
), later_buyers AS (
SELECT DISTINCT user_id AS id FROM pokemon_buys WHERE later = 1
), audiences AS (
SELECT labels.audience, l.id
FROM lookalikes l LEFT JOIN pokemon_viewers v ON v.id = l.id
CROSS JOIN (
SELECT 'lookalikes' AS audience, 0 AS prior_view
UNION ALL SELECT 'lookalikes with prior Pokemon views', 1
UNION ALL SELECT 'lookalikes without prior Pokemon views', 2
) labels
WHERE labels.prior_view = 0
OR (labels.prior_view = 1 AND v.id IS NOT NULL)
OR (labels.prior_view = 2 AND v.id IS NULL)
UNION ALL SELECT 'pokemon viewers', c.id FROM candidates c JOIN pokemon_viewers v ON v.id = c.id
UNION ALL SELECT 'all active shoppers', c.id FROM candidates c
)
SELECT a.audience, COUNT(*) AS shoppers, COUNT(b.id) AS buyers_sep_oct,
CAST(COUNT(b.id) AS DOUBLE) / COUNT(*) AS purchase_rate
FROM audiences a LEFT JOIN later_buyers b ON b.id = a.id
GROUP BY a.audience
ORDER BY purchase_rate DESC;
AudienceShoppersLater buyersPurchase rate
All lookalikes19,1241320.690%
Lookalikes with prior views13,2681300.980%
Lookalikes without prior views5,85620.034%
All previous viewers250,6275720.228%
All eligible non-seed shoppers2,079,4416880.033%

The two prior-view rows partition the lookalike audience. They are not additional shoppers beyond the 19,124 in the first row.

Of the 132 later buyers in the lookalike list, 130 had already viewed Pokemon. The never-viewed group's 0.034% purchase rate is close to the 0.033% eligible baseline. This result supplies little evidence for finding a new audience.

The direct-viewer rule reaches 572 buyers from a much larger list. The campaign list compares the methods at equal list size. Features use the latest retained category attributes.

The capture records the SQL and results used here.

Limits​

  • Builds an exact query-local index over the evaluated dataset relation; it does not persist an ANN index or replace a vector database.
  • The evaluated dataset must be non-empty and k must not exceed its row count. An empty query relation may return an empty result with the stable schema.
  • Dataset and query vector dimensions must match after both relation children are evaluated.
  • Distances repeat between runs; neighbors that tie at the k-th distance can differ, because candidate merge order is not fixed.