Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default defineConfig({
'pgvecto_rs/:dir/:page*': ':dir/:page*',
'vectorchord/usage/multi-vector-retrieval.md': 'vectorchord/usage/indexing-with-maxsim-operators.md',
'vectorchord/usage/similarity-filter.md': 'vectorchord/usage/range-query.md',
'vectorchord/usage/postgresql-tuning.md': 'vectorchord/usage/performance-tuning.md',
'vectorchord/usage/external-build.md': 'vectorchord/usage/external-index-precomputation.md',
},
head: [
Expand Down Expand Up @@ -189,10 +190,9 @@ export default defineConfig({
collapsed: false,
items: [
{ text: 'Indexing', link: '/vectorchord/usage/indexing' },
{ text: 'Search', link: '/vectorchord/usage/search' },
{ text: 'Multi-Vector Retrieval', link: '/vectorchord/usage/indexing-with-maxsim-operators' },
{ text: 'Similarity Filter', link: '/vectorchord/usage/range-query' },
{ text: 'Performance Tuning', link: '/vectorchord/usage/performance-tuning' },
{ text: 'PostgreSQL Tuning', link: '/vectorchord/usage/performance-tuning' },
{ text: 'Monitoring', link: '/vectorchord/usage/monitoring' },
{ text: 'Prewarm', link: '/vectorchord/usage/prewarm' },
{ text: 'Prefilter', link: '/vectorchord/usage/prefilter' },
Expand Down
13 changes: 7 additions & 6 deletions lychee.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ user_agent = "curl/8.1.2"
include_fragments = true
accept = [
200,
403, # forbidden, mainly for OpenAI
999, # LinkedIn
403, # forbidden, mainly for OpenAI
999, # LinkedIn
]
remap = [
"(https://github.com/[^/]+/[^/]+/blob/[^#]+)#[a-zA-Z0-9._-]* $1", # remove fragment from GitHub **blob** URLS
"(https://github.com/[^/]+/[^/]+/tree/[^#]+)#[a-zA-Z0-9._-]* $1", # remove fragment from GitHub **main** URLS
"(https://github.com/[^/]+/[^/]+/blob/[^#]+)#[a-zA-Z0-9._-]* $1", # remove fragment from GitHub **blob** URLS
"(https://github.com/[^/]+/[^/]+/tree/[^#]+)#[a-zA-Z0-9._-]* $1", # remove fragment from GitHub **main** URLS
# `rewrites` from the `.vitepress/config.mts` file
"([\\w]+)/vectorchord/usage/external-index-precomputation $1/vectorchord/usage/external-build",
"([\\w]+)/vectorchord/usage/range-query $1/vectorchord/usage/similarity-filter",
"([\\w]+)/vectorchord/usage/indexing-with-maxsim-operators $1/vectorchord/usage/multi-vector-retrieval",
"([\\w]+)/vectorchord/usage/range-query $1/vectorchord/usage/similarity-filter",
"([\\w]+)/vectorchord/usage/performance-tuning $1/vectorchord/usage/postgresql-tuning",
"([\\w]+)/vectorchord/usage/external-index-precomputation $1/vectorchord/usage/external-build",
]
4 changes: 2 additions & 2 deletions src/pgvecto_rs/faqs/comparison-pgvector.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Comparison with pgvector

Original post: [pgvector vs. pgvecto.rs in 2024: A Comprehensive Comparison for Vector Search in PostgreSQL](https://blog.pgvecto.rs/pgvector-vs-pgvectors-in-2024-a-comprehensive-comparison-for-vector-search-in-postgresql)
Original post: [pgvector vs. pgvecto.rs in 2024: A Comprehensive Comparison for Vector Search in PostgreSQL](https://blog.vectorchord.ai/pgvector-vs-pgvectors-in-2024-a-comprehensive-comparison-for-vector-search-in-postgresql)

TL; DR: Please navigate directly to the [final section](#summary) that contains a table showcasing the main distinctions.

Expand Down Expand Up @@ -40,7 +40,7 @@ Dense vectors are embeddings from neural networks. They are generated by text em

$$D[1\times 256]=\left[ \begin{matrix} 0.342 & 1.774 & 0.087 & 0.870 & 0.001 & \cdots & 0.543 & 0.999 \end{matrix} \right]$$

[pgvecto.rs](https://github.com/tensorchord/pgvecto.rs) supports both dense vector search and [sparse vector search](https://docs.pgvecto.rs/use-case/sparse-vector.html). It provides the ability to use the [`svector`](https://docs.pgvecto.rs/use-case/sparse-vector.html) data type to build sparse vector indexes and perform searches on them.
[pgvecto.rs](https://github.com/tensorchord/pgvecto.rs) supports both dense vector search and [sparse vector search](../use-case/sparse-vector). It provides the ability to use the [`svector`](../use-case/sparse-vector) data type to build sparse vector indexes and perform searches on them.

```sql
CREATE TABLE items (
Expand Down
10 changes: 2 additions & 8 deletions src/vectorchord/getting-started/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,27 +65,21 @@ INSERT INTO items (embedding) SELECT ARRAY[random(), random(), random()]::real[]
With VectorChord, you can create `vchordrq` indexes.

```SQL
CREATE INDEX ON items USING vchordrq (embedding vector_l2_ops) WITH (options = $$
residual_quantization = true
[build.internal]
lists = []
$$);
CREATE INDEX ON items USING vchordrq (embedding vector_l2_ops);
```

And then perform a vector search using `SELECT ... ORDER BY ... LIMIT ...`.

```SQL
SET vchordrq.probes TO '';
SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;
```

For more usage, please read:

- [Indexing](/vectorchord/usage/indexing)
- [Search](/vectorchord/usage/search)
- [Multi-Vector Retrieval](/vectorchord/usage/indexing-with-maxsim-operators)
- [Similarity Filter](/vectorchord/usage/range-query)
- [Performance Tuning](/vectorchord/usage/performance-tuning)
- [PostgreSQL Tuning](/vectorchord/usage/performance-tuning)
- [Monitoring](/vectorchord/usage/monitoring)
- [Prewarm](/vectorchord/usage/prewarm)
- [Prefilter](/vectorchord/usage/prefilter)
Expand Down
3 changes: 1 addition & 2 deletions src/vectorchord/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@
## Usage

- [Indexing](/vectorchord/usage/indexing)
- [Search](/vectorchord/usage/search)
- [Multi-Vector Retrieval](/vectorchord/usage/indexing-with-maxsim-operators)
- [Similarity Filter](/vectorchord/usage/range-query)
- [Performance Tuning](/vectorchord/usage/performance-tuning)
- [PostgreSQL Tuning](/vectorchord/usage/performance-tuning)
- [Monitoring](/vectorchord/usage/monitoring)
- [Prewarm](/vectorchord/usage/prewarm)
- [Prefilter](/vectorchord/usage/prefilter)
Expand Down
2 changes: 1 addition & 1 deletion src/vectorchord/usage/external-build.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# External Build

Unlike pure SQL, external build performs clustering externally before inserting centroids into a PostgreSQL table. While this process may be more complex, it significantly speeds up indexing for larger datasets (>5M). We showed some benchmarks in the [blog post](https://blog.pgvecto.rs/vectorchord-store-400k-vectors-for-1-in-postgresql). It takes around 3 minutes to build an index for 1M vectors, 16x faster than standard indexing in pgvector.
Unlike pure SQL, external build performs clustering externally before inserting centroids into a PostgreSQL table. While this process may be more complex, it significantly speeds up indexing for larger datasets (>5M). We showed some benchmarks in the [blog post](https://blog.vectorchord.ai/vectorchord-store-400k-vectors-for-1-in-postgresql). It takes around 3 minutes to build an index for 1M vectors, 16x faster than standard indexing in pgvector.

To get started, you need to do a clustering of vectors using:
- [faiss](https://github.com/facebookresearch/faiss)
Expand Down
154 changes: 136 additions & 18 deletions src/vectorchord/usage/indexing.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,51 @@ VectorChord's index type `vchordrq` divides vectors into lists and searches only
To build a vector index, start by creating a table named `items` with an `embedding` column of type `vector(n)`, then populate it with sample data.

```sql
CREATE TABLE items (embedding vector(3));
CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3));
INSERT INTO items (embedding) SELECT ARRAY[random(), random(), random()]::real[] FROM generate_series(1, 1000);
```

To create the VectorChord index, you can use the following SQL.
To create a `vchordrq` index, you can use the following SQL.

```sql
CREATE INDEX ON items USING vchordrq (embedding vector_l2_ops);
```

After the index is built, you can perform a vector search using it to retrieve the $10$ nearest neighbors to a vector.

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

You can also add filters to vector search queries as needed.

```sql
SELECT * FROM items WHERE id % 7 <> 0 ORDER BY embedding <-> '[3,1,2]' LIMIT 10;
```

## Tuning

When there are less than $100,000$ rows in the table, you usually don't need to set parameters for search and query.

```sql
CREATE INDEX ON items USING vchordrq (embedding vector_l2_ops);

SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 10;
```

However, as the number of rows grows, partitioning becomes necessary and can be configured using index options. `options` are specified using a [TOML: Tom's Obvious Minimal Language](https://toml.io/) string. You can refer to [#Index Options](#indexing-options) for more information.

```sql
CREATE INDEX ON items USING vchordrq (embedding vector_l2_ops) WITH (options = $$
residual_quantization = true
[build.internal]
lists = [1000]
build_threads = 16
$$);

SET vchordrq.probes TO '10';
SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 10;
```

> [!NOTE]
> - `options` are specified using a [TOML: Tom's Obvious Minimal Language](https://toml.io/) string. You can refer to [#Index Options](#indexing-options) for more information.
> - When dealing with large tables, it will cost huge time and memory for `build.internal`. You can refer to [External Build](external-index-precomputation) to have a better experience.
> - The parameter `lists` should be configured based on the number of rows. The following table provides guidance for this selection. When searching, set `vchordrq.probes` based on the value of `lists`.
The parameter `lists` should be tuned based on the number of rows. The following table provides guidelines for choosing an appropriate value. When querying, choose `vchordrq.probes` accordingly.

| Number of Rows $N$ | Recommended Number of Partitions $L$ | Example `lists` |
| -------------------------------------- | ------------------------------------ | --------------- |
Expand All @@ -32,18 +58,56 @@ $$);
| $N \in [2 \times 10^6, 5 \times 10^7)$ | $L \in [4 \sqrt{N}, 8 \sqrt{N}]$ | `[10000]` |
| $N \in [5 \times 10^7, \infty)$ | $L \in [8 \sqrt{N}, 16\sqrt{N}]$ | `[80000]` |

Then the index will be built internally, and you can perform a vector search with the index.
The process of building an index involves two steps: partitioning the vector space first, and then inserting rows into the index. The first step, partitioning the vector space, can be sped up using multiple threads.

```sql
SET vchordrq.probes = '10';
SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;
CREATE INDEX ON items USING vchordrq (embedding vector_l2_ops) WITH (options = $$
[build.internal]
lists = [1000]
build_threads = 8
$$);

SET vchordrq.probes TO '10';
SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 10;
```

The second step, inserting rows, can be parallelized using multiple processes. Refer to [PostgreSQL Tuning](performance-tuning.md#indexing).

For most datasets using cosine similarity, enabling `residual_quantization` and `build.internal.spherical_centroids` improves both QPS and recall.

```sql
CREATE INDEX ON items USING vchordrq (embedding vector_cosine_ops) WITH (options = $$
residual_quantization = true
[build.internal]
lists = [1000]
spherical_centroids = true
build_threads = 8
$$);

SET vchordrq.probes TO '10';
SELECT * FROM items ORDER BY embedding <=> '[3,1,2]' LIMIT 10;
```

For large tables, the `build.internal` process costs huge time and memory. You can refer to [External Build](external-index-precomputation) to have a better experience.

For large tables, you may opt to use more shared memory to accelerate the process by setting `build.pin` to `true`.

```sql
CREATE INDEX ON items USING vchordrq (embedding vector_l2_ops) WITH (options = $$
residual_quantization = true
build.pin = true
[build.internal]
lists = [1000]
spherical_centroids = true
build_threads = 8
$$);
```

## Reference

### Operator Classes
### Operator Classes <badge type="info" text="vchordrq" /> {#operator-classes}

The table below shows all operator classes for `vchordrq`.
The following table lists all available operator classes supported by `vchordrq`.

| Operator Class | Description | Operator 1 | Operator 2 |
| -------------------- | --------------------------------------------------------------- | ------------------------- | ------------------------ |
Expand All @@ -56,15 +120,23 @@ The table below shows all operator classes for `vchordrq`.
| `vector_maxsim_ops` | index works for `vector[]` type and scalable vector-similarity | `@#(vector[],vector[])` | N/A |
| `halfvec_maxsim_ops` | index works for `halfvec[]` type and scalable vector-similarity | `@#(halfvec[],halfvec[])` | N/A |

`<->`, `<#>` and `<=>` are operators defined by pgvector.

| Name | Description |
| ----- | -------------------------- |
| `<->` | squared Euclidean distance |
| `<#>` | negative dot product |
| `<=>` | cosine distance |

`<<->>`, `<<#>>`, `<<=>>` and `@#` are operators defined by VectorChord.

For more information about `<<->>`, `<<#>>`, `<<=>>`, refer to [Similarity Filter](range-query).

For more information about `@#`, refer to [Multi-Vector Retrieval](indexing-with-maxsim-operators).

The operator classes for `MaxSim` have been available only since version `0.3.0`.
The operator classes for `MaxSim` are available since version `0.3.0`.

### Indexing Options
### Indexing Options <badge type="info" text="vchordrq" /> {#indexing-options}

#### `residual_quantization`

Expand All @@ -75,7 +147,16 @@ The operator classes for `MaxSim` have been available only since version `0.3.0`
- `residual_quantization = false` means that residual quantization is not used.
- `residual_quantization = true` means that residual quantization is used.

### Internal Build Options
#### `build.pin` <badge type="tip" text="since v0.2.1" />

- Description: This index parameter determines whether shared memory is used for indexing. For large tables, you can choose to enable this option to speed up the build process.
- Type: boolean
- Default: `false`
- Example:
- `build.pin = false` means that shared memory is not used.
- `build.pin = true` means that shared memory is used.

### Internal Build Options <badge type="info" text="vchordrq" />

#### `build.internal.lists`

Expand All @@ -88,7 +169,7 @@ The operator classes for `MaxSim` have been available only since version `0.3.0`
- `build.internal.lists = []` means that the vector space is not partitioned.
- `build.internal.lists = [4096]` means the vector space is divided into $4096$ cells.
- `build.internal.lists = [4096, 262144]` means the vector space is divided into $4096$ cells, and those cells are further divided into $262144$ smaller cells.
- Note: The index partitions the vector space into multiple Voronoi cells using centroids, iteratively creating a hierarchical space partition tree. Each leaf node in this tree represents a region with an associated list storing vectors in that region. During insertion, vectors are placed in lists corresponding to their appropriate leaf nodes. For queries, the index optimizes search by excluding lists whose leaf nodes are distant from the query vector, effectively pruning the search space. If the length of `lists` is $1$, the `lists` option should be no less than $4 * \sqrt{N}$, where $N$ is the number of vectors in the table.
- Note: The index partitions the vector space into multiple Voronoi cells based on centroids, iteratively creating a hierarchical space partition tree. Each leaf node in this tree represents a region with an associated list storing vectors in that region. During insertion, vectors are placed in lists corresponding to their appropriate leaf nodes. For queries, the index optimizes search by excluding lists whose leaf nodes are distant from the query vector, effectively pruning the search space. If the length of `lists` is $1$, the `lists` option should be no less than $4 * \sqrt{N}$, where $N$ is the number of vectors in the table.

#### `build.internal.spherical_centroids`

Expand Down Expand Up @@ -120,7 +201,7 @@ The operator classes for `MaxSim` have been available only since version `0.3.0`
- `build.internal.kmeans_iterations = 10` means that the K-means algorithm performs $10$ iterations.
- `build.internal.kmeans_iterations = 100` means that the K-means algorithm performs $100$ iterations.

#### `build.internal.build_threads` {#build-internal-build-threads}
#### `build.internal.build_threads`

- Description: This index parameter determines the number of threads used by K-means algorithm. The higher this value, the faster the build, and greater load on the server in building.
- Type: integer
Expand All @@ -129,3 +210,40 @@ The operator classes for `MaxSim` have been available only since version `0.3.0`
- Example:
- `build.internal.build_threads = 1` means that the K-means algorithm uses $1$ thread.
- `build.internal.build_threads = 4` means that the K-means algorithm uses $4$ threads.

### Search Parameters <badge type="info" text="vchordrq" />

#### `vchordrq.probes`

- Description: This GUC parameter `vchordrq.probes` controls how the vector space assists in query pruning. The more probes, the more accurate the search, but also the slower it is.
- Type: list of integers
- Default:
- ` ` <badge type="tip" text="since v0.3.0" />
- `10` <badge type="tip" text="until v0.2.2: the default value was 10 before `lists` defaulted to empty" />
- Example:
- `SET vchordrq.probes = 1` means that only one probe is used.
- `SET vchordrq.probes = 10` means that ten probes are used.
- Note: The default value is an empty list. The length of this option must match the length of `lists`.
- If `lists = []`, then probes must be ` `.
- If `lists = [11, 22]`, then probes can be `2,4` or `4,8`. It must not be incorrectly shaped, for example, ` `, `3`, `7,8,9`, `5,5,5,5`.

#### `vchordrq.epsilon`

- Description: Even after pruning, the number of retrieved vectors remains substantial. The index employs the RaBitQ algorithm to quantize vectors into bit vectors, which require just $\frac{1}{32}$ the memory of single-precision floating-point vectors. Most computations are integer-based, leading to faster processing. Unlike conventional quantization algorithms, RaBitQ estimates not only distances but also their lower bounds. The index computes the lower bound for each vector and dynamically adjusts the number of vectors needing recalculated distances, based on the query count, thus balancing performance and accuracy. The GUC parameter `vchordrq.epsilon` controls the conservativeness of the lower bounds of distances. The higher the value, the higher the accuracy, but the worse the performance. The default value tends to favor higher accuracy than needed for most use cases, so you can try lowering this parameter to achieve better performance.
- Type: float
- Default: `1.9`
- Domain: `[0.0, 4.0]`
- Example:
- `SET vchordrq.epsilon = 0.1` indicates you are using a very optimistic lower bound estimation. You set it this way because your dataset is not sensitive to the lower bound estimation, for the precision you need.
- `SET vchordrq.epsilon = 4.0` indicates you are using a very pessimistic lower bound estimation. You set it this way because your dataset is not very sensitive to the lower bound estimation, for the precision you need.

#### `vchordrq.prewarm_dim` <badge type="danger" text="deprecated in v0.4.0" />

- Description: The `vchordrq.prewarm_dim` GUC parameter is used to precompute the RaBitQ projection matrix for the specified dimensions. This can help to reduce the latency of the first query after the PostgreSQL cluster is started.
- Type: list of integers
- Default: `64,128,256,384,512,768,1024,1536`
- Example:
- `ALTER SYSTEM SET vchordrq.prewarm_dim = '64,128'` means that the projection matrix will be precomputed for dimensions 64 and 128.
- Note:
- This setting requires a database restart to take effect.
- Since `v0.4.0`, a new algorithm made this option obsolete.
Loading