mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-22 20:15:46 +08:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb72a6c063 | ||
|
|
f32f695844 | ||
|
|
1b013a94f7 | ||
|
|
00148dfa1f | ||
|
|
67fc791d95 |
@@ -1,3 +1,7 @@
|
|||||||
|
## 0.4.2 (unreleased)
|
||||||
|
|
||||||
|
- Added notice when index created with little data
|
||||||
|
|
||||||
## 0.4.1 (2023-03-21)
|
## 0.4.1 (2023-03-21)
|
||||||
|
|
||||||
- Improved performance of cosine distance
|
- Improved performance of cosine distance
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -153,15 +153,11 @@ By default, pgvector performs exact nearest neighbor search, which provides perf
|
|||||||
|
|
||||||
You can add an index to use approximate nearest neighbor search, which trades some recall for performance. Unlike typical indexes, you will see different results for queries after adding an approximate index.
|
You can add an index to use approximate nearest neighbor search, which trades some recall for performance. Unlike typical indexes, you will see different results for queries after adding an approximate index.
|
||||||
|
|
||||||
Two keys to achieving good recall are:
|
Three keys to achieving good recall are:
|
||||||
|
|
||||||
1. Create the index *after* the table has some data
|
1. Create the index *after* the table has some data
|
||||||
2. Choose an appropriate number of lists (lower is better for recall, higher is better for speed)
|
2. Choose an appropriate number of lists (a good place to start is `rows / 1000` for up to 1M rows and `sqrt(rows)` for over 1M rows)
|
||||||
|
3. When querying, specify an appropriate number of [probes](#query-options) (higher is better for recall, lower is better for speed)
|
||||||
A good place to start is:
|
|
||||||
|
|
||||||
- `rows / 1000` for up to 1M rows
|
|
||||||
- `sqrt(rows)` for over 1M rows
|
|
||||||
|
|
||||||
Add an index for each distance function you want to use.
|
Add an index for each distance function you want to use.
|
||||||
|
|
||||||
@@ -190,7 +186,7 @@ Vectors with up to 2,000 dimensions can be indexed.
|
|||||||
Specify the number of probes (1 by default)
|
Specify the number of probes (1 by default)
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
SET ivfflat.probes = 1;
|
SET ivfflat.probes = 10;
|
||||||
```
|
```
|
||||||
|
|
||||||
A higher value provides better recall at the cost of speed, and it can be set to the number of lists for exact nearest neighbor search (at which point the planner won’t use the index)
|
A higher value provides better recall at the cost of speed, and it can be set to the number of lists for exact nearest neighbor search (at which point the planner won’t use the index)
|
||||||
@@ -199,7 +195,7 @@ Use `SET LOCAL` inside a transaction to set it for a single query
|
|||||||
|
|
||||||
```sql
|
```sql
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET LOCAL ivfflat.probes = 1;
|
SET LOCAL ivfflat.probes = 10;
|
||||||
SELECT ...
|
SELECT ...
|
||||||
COMMIT;
|
COMMIT;
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -431,8 +431,18 @@ ComputeCenters(IvfflatBuildState * buildstate)
|
|||||||
/* TODO Ensure within maintenance_work_mem */
|
/* TODO Ensure within maintenance_work_mem */
|
||||||
buildstate->samples = VectorArrayInit(numSamples, buildstate->dimensions);
|
buildstate->samples = VectorArrayInit(numSamples, buildstate->dimensions);
|
||||||
if (buildstate->heap != NULL)
|
if (buildstate->heap != NULL)
|
||||||
|
{
|
||||||
SampleRows(buildstate);
|
SampleRows(buildstate);
|
||||||
|
|
||||||
|
if (buildstate->samples->length < buildstate->lists)
|
||||||
|
{
|
||||||
|
ereport(NOTICE,
|
||||||
|
(errmsg("ivfflat index created with little data"),
|
||||||
|
errdetail("this will cause poor recall"),
|
||||||
|
errhint("drop the index until the table has more data")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate centers */
|
/* Calculate centers */
|
||||||
IvfflatBench("k-means", IvfflatKmeans(buildstate->index, buildstate->samples, buildstate->centers));
|
IvfflatBench("k-means", IvfflatKmeans(buildstate->index, buildstate->samples, buildstate->centers));
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int ivfflat_probes;
|
int ivfflat_probes;
|
||||||
int ivfflat_bound;
|
|
||||||
static relopt_kind ivfflat_relopt_kind;
|
static relopt_kind ivfflat_relopt_kind;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -33,10 +32,6 @@ _PG_init(void)
|
|||||||
DefineCustomIntVariable("ivfflat.probes", "Sets the number of probes",
|
DefineCustomIntVariable("ivfflat.probes", "Sets the number of probes",
|
||||||
"Valid range is 1..lists.", &ivfflat_probes,
|
"Valid range is 1..lists.", &ivfflat_probes,
|
||||||
1, 1, IVFFLAT_MAX_LISTS, PGC_USERSET, 0, NULL, NULL, NULL);
|
1, 1, IVFFLAT_MAX_LISTS, PGC_USERSET, 0, NULL, NULL, NULL);
|
||||||
|
|
||||||
DefineCustomIntVariable("ivfflat.bound", "Sets the max results from index (experimental)",
|
|
||||||
NULL, &ivfflat_bound,
|
|
||||||
0, 0, INT_MAX, PGC_USERSET, 0, NULL, NULL, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -78,7 +78,6 @@
|
|||||||
|
|
||||||
/* Variables */
|
/* Variables */
|
||||||
extern int ivfflat_probes;
|
extern int ivfflat_probes;
|
||||||
extern int ivfflat_bound;
|
|
||||||
|
|
||||||
/* Exported functions */
|
/* Exported functions */
|
||||||
PGDLLEXPORT void _PG_init(void);
|
PGDLLEXPORT void _PG_init(void);
|
||||||
|
|||||||
@@ -124,11 +124,7 @@ GetScanItems(IndexScanDesc scan, Datum value)
|
|||||||
*
|
*
|
||||||
* See postgres/src/backend/storage/buffer/README for description
|
* See postgres/src/backend/storage/buffer/README for description
|
||||||
*/
|
*/
|
||||||
BufferAccessStrategy bas = GetAccessStrategy(BAS_BULKREAD);
|
BufferAccessStrategy bas = GetAccessStrategy(BAS_NORMAL);
|
||||||
|
|
||||||
/* Set the max number of results */
|
|
||||||
if (ivfflat_bound > 0)
|
|
||||||
tuplesort_set_bound(so->sortstate, ivfflat_bound);
|
|
||||||
|
|
||||||
/* Search closest probes lists */
|
/* Search closest probes lists */
|
||||||
while (!pairingheap_is_empty(so->listQueue))
|
while (!pairingheap_is_empty(so->listQueue))
|
||||||
|
|||||||
Reference in New Issue
Block a user