Skip to content

Indexing

Indexing is the process of building a data structure that allows for efficient search. pgvecto.rs supports three indexing algorithms: brute force (FLAT), IVF, and HNSW. The default algorithm is HNSW.

Assuming there is a table items and there is a column named embedding of type vector(n), you can create a vector index for squared Euclidean distance with the following SQL.

sql
CREATE INDEX ON items USING vectors (embedding vector_l2_ops);

The vector_l2_ops is an operator class for squared Euclidean distance. There are all operator classes for each vector type and distance type.

Vector typeDistance typeOperator class
vectorsquared Euclidean distancevector_l2_ops
vectornegative dot productvector_dot_ops
vectorcosine distancevector_cos_ops
vecf16squared Euclidean distancevecf16_l2_ops
vecf16negative dot productvecf16_dot_ops
vecf16cosine distancevecf16_cos_ops

Now you can perform a KNN search with the following SQL again, this time the vector index is used for searching.

sql
SELECT * FROM items ORDER BY embedding <-> '[3,2,1]' LIMIT 5;
Details

pgvecto.rs constructs the index asynchronously. When you insert new rows into the table, they will first be placed in an append-only file. The background thread will periodically merge the newly inserted row to the existing index. When a user performs any search prior to the merge process, it scans the append-only file to ensure accuracy and consistency.

Options

We utilize TOML syntax to express the index's configuration. Here's what each key in the configuration signifies:

KeyTypeDescription
segmenttableOptions for segments.
optimizingtableOptions for background optimizing.
indexingtableThe algorithm to be used for indexing.

Options for table segment.

KeyTypeRangeDefaultDescription
max_growing_segment_sizeinteger[1, 4_000_000_000]20_000Maximum size of unindexed vectors.
max_sealed_segment_sizeinteger[1, 4_000_000_000]1_000_000Maximum size of vectors for indexing.

Options for table optimizing.

KeyTypeRangeDefaultDescription
optimizing_threadsinteger[1, 65535]sqrt of the number of coresMaximum threads for indexing.
sealing_secsinteger[1, 60]60See below.
sealing_sizeinteger[1, 4_000_000_000]1See below.

If a write segment larger than sealing_size do not accept new data for sealing_secs seconds, the write segment will be turned to a sealed segment.

Options for table indexing.

KeyTypeDescription
flattableIf this table is set, brute force algorithm will be used for the index.
ivftableIf this table is set, IVF will be used for the index.
hnswtableIf this table is set, HNSW will be used for the index.

You can choose only one algorithm in above indexing algorithms. Default value is hnsw.

Options for table flat.

KeyTypeDescription
quantizationtableThe algorithm to be used for quantization.

Options for table ivf.

KeyTypeRangeDefaultDescription
nlistinteger[1, 1_000_000]1000Number of cluster units.
nsampleinteger[1, 1_000_000]65536Number of samples for K-Means clustering.
least_iterationsinteger[1, 1_000_000]16Least iterations for K-Means clustering.
iterationsinteger[1, 1_000_000]500Max iterations for K-Means clustering.
quantizationtableThe quantization algorithm to be used.

Options for table hnsw.

KeyTypeRangeDefaultDescription
minteger[4, 128]12Maximum degree of the node.
ef_constructioninteger[10, 2000]300Search scope in building.
quantizationtableThe quantization algorithm to be used.

Options for table quantization.

KeyTypeDescription
trivialtableIf this table is set, no quantization is used.
scalartableIf this table is set, scalar quantization is used.
producttableIf this table is set, product quantization is used.

You can choose only one algorithm in above indexing algorithms. Default value is trivial.

Options for table product.

KeyTypeRangeDefaultDescription
sampleinteger[1, 1_000_000]65535Samples to be used for quantization.
ratioenum"x4", "x8", "x16", "x32", "x64""x4"Compression ratio for quantization.

Compression ratio is how many memory you are saved for saving vectors. For example, "x4" is compared to before. If you are creating indexes on vecf16, "x4" is compared to before.

Examples

There are some examples.

sql
-- HNSW algorithm, default settings.

CREATE INDEX ON items USING vectors (embedding vector_l2_ops);

--- Or using bruteforce with PQ.

CREATE INDEX ON items USING vectors (embedding vector_l2_ops)
WITH (options = $$
[indexing.flat]
quantization.product.ratio = "x16"
$$);

--- Or using IVFPQ algorithm.

CREATE INDEX ON items USING vectors (embedding vector_l2_ops)
WITH (options = $$
[indexing.ivf]
quantization.product.ratio = "x16"
$$);

-- Use more threads for background building the index.

CREATE INDEX ON items USING vectors (embedding vector_l2_ops)
WITH (options = $$
optimizing.optimizing_threads = 16
$$);

-- Prefer smaller HNSW graph.

CREATE INDEX ON items USING vectors (embedding vector_l2_ops)
WITH (options = $$
segment.max_growing_segment_size = 200000
$$);