-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: cutecutecat <junyuchen@tensorchord.ai>
- Loading branch information
1 parent
76c2cf9
commit 60e185f
Showing
4 changed files
with
91 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Indexing Options | ||
|
||
Search options are specified by [PostgreSQL GUC](https://www.postgresql.org/docs/current/config-setting.html). | ||
|
||
## Options for `ivf` | ||
|
||
These options only work at `ivf` indexing algorithm. | ||
For `ivf` algorithm, refer to the [indexing document](../usage/indexing.html#inverted-file-index-ivf). | ||
|
||
| Option | Type | Range | Default | Description | | ||
| ------------------------ | ------- | ---------------- | ------- | ----------------------------------------- | | ||
| vectors.ivf_nprobe | integer | `[1, 1_000_000]` | `10` | Number of lists to scan. | | ||
|
||
## Options for `hnsw` | ||
|
||
These options only work at `hnsw` indexing algorithm. | ||
For `ivf` algorithm, refer to the [indexing document](../usage/indexing.html#hierarchical-navigable-small-world-graph-hnsw). | ||
|
||
| Option | Type | Range | Default | Description | | ||
| ------------------------ | ------- | -------------- | ------- | ----------------------------------------- | | ||
| vectors.hnsw_ef_search | integer | `[1, 65535]` | `100` | Search scope of HNSW. | | ||
|
||
## Other Options | ||
|
||
Query options for search mode: | ||
|
||
These options only work at `hnsw` indexing algorithm. | ||
For search mode, refer to the [search document](../usage/search.html#Search modes). | ||
|
||
| Option | Type | Range | Default | Description | | ||
| ------------------------ | ------- | ------------------ | --------- | -------------------------------------- | | ||
| vectors.search_mode | enum | `"basic", "vbase"` | `"vbase"` | Search mode. | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,83 +1,76 @@ | ||
# Search | ||
|
||
The SQL for searching is very simple. Here is an example of searching the $5$ nearest embedding in table `items`: | ||
|
||
Get the nearest 5 neighbors to a vector | ||
```sql | ||
SET vectors.hnsw_ef_search = 64; | ||
SELECT * FROM items ORDER BY embedding <-> '[3,2,1]' LIMIT 5; | ||
``` | ||
|
||
The vector index will search for `64` nearest rows, and `5` nearest rows is gotten since there is a `LIMIT` clause. | ||
## Operators | ||
|
||
## Search modes | ||
These operators are used for distance metrics: | ||
|
||
There are two search modes: `basic` and `vbase`. | ||
| Name | Description | | ||
| ---- | -------------------------- | | ||
| <-> | squared Euclidean distance | | ||
| <#> | negative dot product | | ||
| <=> | cosine distance | | ||
|
||
### `basic` | ||
For their definitions, see [overview](../getting-started/overview). | ||
|
||
`basic` is the default search mode. In this mode, vector indexes behave like a vector search library. It works well if all of your queries is like this: | ||
## Filter | ||
|
||
For a given category, get the nearest 10 neighbors to a vector | ||
```sql | ||
SELECT * FROM items ORDER BY embedding <-> '[3,2,1]' LIMIT 5; | ||
SELECT 1 FROM items WHERE category_id = 1 ORDER BY embedding <#> '[0.5,0.5,0.5]' limit 10 | ||
``` | ||
|
||
It's recommended if your do **not** take advantages of | ||
|
||
* database transaction | ||
* deletions without `VACUUM` | ||
* WHERE clauses and very complex SQL statements | ||
|
||
### `vbase` | ||
|
||
`vbase` is another search mode. In this mode, vector indexes behave like a database index. In `vbase` mode, searching results become a stream and every time the database pulls a row, the vector index computes a row to return. It's quite different from an ordinary vector search if you are using a vector search library, such as *faiss*. The latter always wants to know how many results are needed before searching. The original idea comes from [VBASE: Unifying Online Vector Similarity Search and Relational Queries via Relaxed Monotonicity](https://www.usenix.org/conference/osdi23/presentation/zhang-qianxi). | ||
|
||
Assuming you are using HNSW algorithm, you may want the following SQL to work: | ||
## Query options | ||
|
||
Set `ivf` scan lists to 1 in session: | ||
```sql | ||
SET vectors.hnsw_ef_search = 64; | ||
SELECT * FROM items ORDER BY embedding <-> '[3,2,1]' WHERE id % 2 = 0 LIMIT 64; | ||
SET vectors.ivf_nprobe=1; | ||
``` | ||
|
||
In `basic` mode, you may only get `32` rows because the HNSW algorithm does search simply so the filter condition is ignored. | ||
|
||
In `vbase` mode, the HNSW algorithm is guaranteed to return rows as many as you need, so you can always get correct behavior if your do take advantages of: | ||
|
||
* database transaction | ||
* deletions without `VACUUM` | ||
* `WHERE` clauses and very complex SQL statements | ||
Set `hnsw` search scope to 40 in transaction: | ||
```sql | ||
SET LOCAL vectors.hnsw_ef_search=40; | ||
``` | ||
|
||
You can enable `vbase` by a SQL statement `SET vectors.search_mode = vbase;`. | ||
For all options, refer to [search options](../reference/search_options.html). | ||
|
||
## Prefilter | ||
## Advanced usage | ||
|
||
If your queries include a `WHERE` clause, you can set set search mode to `vbase`. It's good and it even works on all conditions. `vbase` is a **postfilter** method: it pulls rows as many as you need, but it scans rows that you may not need. Since some rows will definitely be removed by the `WHERE` clause, we can skip scanning them, which will make the search faster. We call it **prefilter**. | ||
In traditional vector database, sometimes you expect the search to return the exact number of vectors equal to `LIMIT`, but it can't: | ||
```sql | ||
SELECT COUNT(1) FROM (SELECT 1 FROM t WHERE (category_id = 1) ORDER BY val <-> '[1,1,1]' limit 10) t2; | ||
--- returns 1, much less than 10 | ||
``` | ||
That is why we introduce `vbase` search mode and set it as default. | ||
|
||
Prefilter speeds your query in the following condition: | ||
### Search modes | ||
|
||
* You create a multicolumn vector index containing a vector column and many payload columns. | ||
* The `WHERE` clause in a query is just simple like `(id % 2 = 0) AND (age > 50)`. | ||
There are two search modes: `vbase` and `basic`. | ||
|
||
Prefilter is also used in internal implementation for handling deleted rows in `pgvecto.rs`. | ||
### `vbase` | ||
|
||
Prefilter may have a negative impact on precision. Test the precision before using it. | ||
As the default search mode, `vbase` is suitable for most scenarios. | ||
It would return enough vectors for your filter as far as it could. | ||
|
||
Prefilter is enabled by default because it almost only works if you create a multicolumn vector index. | ||
For how it works, refer to the thesis [VBASE: Unifying Online Vector Similarity Search and Relational Queries via Relaxed Monotonicity](https://www.usenix.org/conference/osdi23/presentation/zhang-qianxi). | ||
|
||
## Options | ||
It's recommended to use `vbase` in these situations: | ||
|
||
Search options are specified by PostgreSQL GUC. You can use `SET` command to apply these options in session or `SET LOCAL` command to apply these options in transaction. | ||
* Search with filter or transaction | ||
* Returning sufficient vectors is important | ||
* Tired of tuning query options in `basic` mode | ||
|
||
Runtime parameters for planning a query: | ||
### `basic` | ||
`basic` is behaviorally consistent with traditional vector databases. | ||
It will be useful if you want to align other vector databases. | ||
|
||
| Option | Type | Range | Default | Description | | ||
| -------------------- | ------- | ------------------ | --------- | ---------------------------------------------------------------------------- | | ||
| vectors.enable_index | boolean | | `on` | Enables or disables the query planner's use of vector index-scan plan types. | | ||
| vectors.search_mode | enum | `"basic", "vbase"` | `"basic"` | Search mode. | | ||
Enabling `basic`, you must respect these restrictions: | ||
|
||
Runtime parameters for executing a query: | ||
* Search without filter and transaction | ||
* Returning insufficient vectors is acceptable | ||
|
||
| Option | Type | Range | Default | Description | | ||
| ------------------------ | ------- | -------------- | ------- | ----------------------------------------- | | ||
| vectors.enable_prefilter | boolean | | `on` | Enables or disables the use of prefilter. | | ||
| vectors.ivf_nprobe | integer | `[1, 1000000]` | `10` | Number of lists to scan. | | ||
| vectors.hnsw_ef_search | integer | `[1, 65535]` | `100` | Search scope of HNSW. | |