Applies to VAST Cluster 5.5.
This page lists the SQL that VAST Vector Search accepts in VAST Cluster 5.5: the vector column types, the CREATE TABLE ... VECTOR CLUSTER BY grammar, the distance functions, the query shape that uses the index, and the errors you get when a statement isn't allowed. You send this SQL to the VAST Query Engine through the ADBC driver.
For the rest of the SQL the VAST Query Engine supports, see the VAST DataBase SQL reference.
Vector column types
A vector is a column type on VAST DataBase tables. Its length (the dimension) is fixed when you create the table.
| Type | Notes |
|---|---|
VECTOR(FLOAT, <dim>) |
32-bit floats. Can be indexed. |
VECTOR(FLOAT16, <dim>) |
16-bit floats. Can be indexed. HALF is accepted as an alias. DESCRIBE shows it as VECTOR(HALF_FLOAT, <dim>). |
VECTOR(INTEGER, <dim>) |
The type exists (supported data types), and you can use it as an ordinary column. Index FLOAT or FLOAT16 vectors: VECTOR CLUSTER BY on a VECTOR(INTEGER, <dim>) column is accepted, but an INSERT into that table then fails with a generic internal error (status: 17). |
Rules for vector values:
- The value's length must match the column's dimension. An insert with the wrong length fails.
FLOAT[]andINTEGER[]lists aren't vector columns, and you can't use them withVECTOR CLUSTER BY.- Trino and Spark have no type for a vector column; see limits.
-- fails: wrong length (the table's vector column is VECTOR(FLOAT, 8))
INSERT INTO "bucket/schema".docs VALUES (5, 'e', [1,2,3,4,5,6,7]::FLOAT[7]);
-- Conversion Error: Cannot cast array of size 7 to array of size 8
CREATE TABLE with a vector index
You create the vector index when you create the table, with VECTOR CLUSTER BY. This is the grammar VAST Cluster 5.5 accepts:
CREATE [OR REPLACE] TABLE [IF NOT EXISTS] "bucket/schema".name (
col1 TYPE,
embedding VECTOR(FLOAT, d),
...
)
VECTOR CLUSTER BY embedding (
metric = 'l2sq' | 'cosine' | 'ip',
cluster_quantization = 'none' | 'scalar_8bit',
search_quantization = 'none' | 'scalar_8bit'
);
| Property | Required | Values | Default |
|---|---|---|---|
metric |
Yes | 'l2sq' (Euclidean), 'cosine', 'ip' (inner product) |
None |
cluster_quantization |
No | 'none', 'scalar_8bit' |
'scalar_8bit' |
search_quantization |
No | 'none', 'scalar_8bit' |
'scalar_8bit' |
Rules:
- There's no
CREATE VECTOR INDEX,DROP VECTOR INDEXorALTER VECTOR INDEX. To remove the index, drop the table. - You can index one vector column per table. The table can have other, un-indexed vector columns.
metricis required, and you can give it only once. A secondmetricgivesParser Error: Duplicate attribute: 'metric'.- The column in
VECTOR CLUSTER BYmust be aVECTOR(...)column, notVARCHAR,INTEGERor a list. metric,cluster_quantizationandsearch_quantizationare the only properties. Any other property is rejected.- If
search_quantizationis'none',cluster_quantizationmust be'none'too. Quantization has the table of allowed pairs. - You can't change the metric or the quantization after you create the table.
ALTER TABLE ... ALTER COLUMN ... SET DATA TYPEon the indexed column fails withThis functionality is not implemented yet. The full list of create-time rules is on limits. vectoris a reserved word in the VAST Query Engine, so don't name your vector columnvector. Use a name such asembedding.
For the step-by-step version, see create an index.
DESCRIBE and SHOW
DESCRIBE "bucket/schema".name;
SHOW "bucket/schema".name;
Both list the columns. The vector column shows as VECTOR(FLOAT, d) (or VECTOR(HALF_FLOAT, d)), but nothing shows the index itself: its metric and quantization aren't listed. There's no SHOW VECTOR INDEX.
To read a table's index settings, use the Python SDK's table.vector_index. It returns the column, metric, distance function and both quantization settings. The same settings are in the table's Arrow schema as the SDK returns it (table.arrow_schema.metadata), under the key VAST:vector_index_spec. The ADBC driver's adbc_get_table_schema() doesn't return them.
Changing data (DML)
Use the standard INSERT, UPDATE and DELETE commands of the VAST Query Engine. On a vector-indexed table:
- You can update the other (metadata) columns, and delete rows.
- You can't update the vector column. To change a vector, delete the row and insert it again with the new vector.
- You can't add or drop columns (
ALTER TABLE ... ADD COLUMNandDROP COLUMNfail withInvalid Argument). - You can't rename the indexed vector column. It fails with
Tried to drop a column which cannot be dropped.
Distance functions
| Function | Use with metric | Smaller result means |
|---|---|---|
array_distance(a, b) |
l2sq |
closer |
array_cosine_distance(a, b) |
cosine |
closer |
array_negative_inner_product(a, b) |
ip |
more similar |
array_inner_product(a, b) |
(none) | less similar |
The operators <-> and <=> compute the same distances as array_distance and array_cosine_distance, but a search written with them doesn't use the index. <#> isn't accepted.
All four functions work on any vector column, indexed or not. The index is used only when the function in ORDER BY matches the table's metric, as in the "Use with metric" column. The examples here cast the column to a fixed-size array of the same dimension (embedding::FLOAT[8]), as the Python SDK does.
Inner product: for an ip table, order by array_negative_inner_product. array_inner_product returns the plain inner product, so ORDER BY ... ASC puts the least similar rows first, and the index isn't used. The Python SDK's vector_search() makes this mistake on ip tables; see Python SDK.
Query shape that uses the index
The VAST Query Engine uses the vector index only for a query of this shape:
SELECT id, title,
array_distance(embedding::FLOAT[8], [1,1,1,1,1,1,1,1]::FLOAT[8]) AS dist
FROM "bucket/schema".docs
WHERE title <> 'x'
ORDER BY dist
LIMIT 10;
ORDER BYhas exactly one key: the distance expression, in ascending order (the default).LIMIT kis present.- There's no
OFFSET. A query withOFFSETstill runs and returns results, but it doesn't use the index. - The query reads one vector-indexed table.
WHEREfilters and extra columns are allowed.
Any other shape runs as a full scan of the table and returns exact results, which can be slow on a large table. EXPLAIN shows which you have: the plan of a query that uses the index contains a VAST_VEC_INDEX_SCAN step, while a full scan shows only TOP_N over a VAST_SCAN of the table. Query design explains the shape rules, with the rewrites for queries that don't use the index. For filters, see filters.
Aggregating the search results (GROUP BY, count(DISTINCT ...)) runs into the Query Engine's aggregate restrictions; see the VAST DataBase SQL reference.
Errors you'll see
These are the errors VAST Cluster 5.5 returns for statements that aren't allowed.
-- not a vector column
CREATE TABLE t (name VARCHAR) VECTOR CLUSTER BY name (metric = 'l2sq');
-- Binder Error: Vector index column "name" must be a vector column, but has type: VARCHAR
-- a list, not a vector
CREATE TABLE t (arr FLOAT[]) VECTOR CLUSTER BY arr (metric = 'l2sq');
-- Binder Error: Vector index column "arr" must be a vector column, but has type: FLOAT[]
-- a fixed-size array column
CREATE TABLE t (arr INTEGER[4]) VECTOR CLUSTER BY arr (metric = 'l2sq');
-- Binder Error: ARRAY type is not supported in table definitions. Column "arr" has type: INTEGER[4]
-- metric given twice
CREATE TABLE t (e VECTOR(FLOAT, 4)) VECTOR CLUSTER BY e (metric = 'l2sq', metric = 'ip');
-- Parser Error: Duplicate attribute: 'metric'
-- no property list
CREATE TABLE t (e VECTOR(FLOAT, 4)) VECTOR CLUSTER BY e;
-- Parser Error: syntax error at end of input
-- no such statement
CREATE VECTOR INDEX ix ON t (e);
SHOW VECTOR INDEX t;
-- Parser Error: syntax error at or near "VECTOR"
-- no such function (use array_cosine_distance)
SELECT id, cosine_similarity(e, [1,0,0,0]::FLOAT[4]) AS sim FROM t ORDER BY sim DESC LIMIT 10;
-- Catalog Error: Scalar Function with name cosine_similarity does not exist!
-- ORDER BY a distance without LIMIT
SELECT id FROM t ORDER BY array_distance(e::FLOAT[4], [1,0,0,0]::FLOAT[4]);
-- The operator 'ORDER_BY' type=1 is currently not supported for this usage.
The cluster returns a bare Invalid Argument (for example internal error: Invalid Argument) when:
- the metric is missing or isn't
l2sq,cosineorip - a quantization value isn't
noneorscalar_8bit - the quantization pair isn't allowed (
scalar_8bit/none) - there's an unknown property in
VECTOR CLUSTER BY - you update the vector column, or add or drop a column
The message doesn't say which of these it is, so check your statement against the rules on this page. For more errors and fixes, see the error index.
See also
- Python SDK reference: vector index
- Configuration: session settings for search
- Limits
- Cheat sheet