mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-22 20:15:46 +08:00
Compare commits
1 Commits
dynamic-pr
...
bas
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb72a6c063 |
@@ -1,7 +1,6 @@
|
|||||||
## 0.4.2 (unreleased)
|
## 0.4.2 (unreleased)
|
||||||
|
|
||||||
- Added notice when index created with little data
|
- Added notice when index created with little data
|
||||||
- Fixed installation error with Postgres 12.0-12.2
|
|
||||||
|
|
||||||
## 0.4.1 (2023-03-21)
|
## 0.4.1 (2023-03-21)
|
||||||
|
|
||||||
|
|||||||
25
README.md
25
README.md
@@ -2,11 +2,7 @@
|
|||||||
|
|
||||||
Open-source vector similarity search for Postgres
|
Open-source vector similarity search for Postgres
|
||||||
|
|
||||||
Supports
|
Supports exact and approximate nearest neighbor search for L2 distance, inner product, and cosine distance
|
||||||
|
|
||||||
- exact and approximate nearest neighbor search
|
|
||||||
- L2 distance, inner product, and cosine distance
|
|
||||||
- any [language](#languages) with a Postgres client
|
|
||||||
|
|
||||||
[](https://github.com/pgvector/pgvector/actions)
|
[](https://github.com/pgvector/pgvector/actions)
|
||||||
|
|
||||||
@@ -40,7 +36,7 @@ Create a vector column with 3 dimensions
|
|||||||
CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3));
|
CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3));
|
||||||
```
|
```
|
||||||
|
|
||||||
Insert vectors
|
Insert values
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[4,5,6]');
|
INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[4,5,6]');
|
||||||
@@ -128,7 +124,7 @@ SELECT embedding <-> '[3,1,2]' AS distance FROM items;
|
|||||||
For inner product, multiply by -1 (since `<#>` returns the negative inner product)
|
For inner product, multiply by -1 (since `<#>` returns the negative inner product)
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
SELECT (embedding <#> '[3,1,2]') * -1 AS inner_product FROM items;
|
SELECT -1 * (embedding <#> '[3,1,2]') AS inner_product FROM items;
|
||||||
```
|
```
|
||||||
|
|
||||||
For cosine similarity, use 1 - cosine distance
|
For cosine similarity, use 1 - cosine distance
|
||||||
@@ -137,7 +133,7 @@ For cosine similarity, use 1 - cosine distance
|
|||||||
SELECT 1 - (embedding <=> '[3,1,2]') AS cosine_similarity FROM items;
|
SELECT 1 - (embedding <=> '[3,1,2]') AS cosine_similarity FROM items;
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Aggregates
|
#### Averaging
|
||||||
|
|
||||||
Average vectors
|
Average vectors
|
||||||
|
|
||||||
@@ -160,8 +156,8 @@ You can add an index to use approximate nearest neighbor search, which trades so
|
|||||||
Three 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 - a good place to start is `rows / 1000` for up to 1M rows and `sqrt(rows)` for over 1M rows
|
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 `lists / 10` for up to 1M rows and `sqrt(lists)` 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)
|
||||||
|
|
||||||
Add an index for each distance function you want to use.
|
Add an index for each distance function you want to use.
|
||||||
|
|
||||||
@@ -279,10 +275,8 @@ Language | Libraries / Examples
|
|||||||
--- | ---
|
--- | ---
|
||||||
C++ | [pgvector-cpp](https://github.com/pgvector/pgvector-cpp)
|
C++ | [pgvector-cpp](https://github.com/pgvector/pgvector-cpp)
|
||||||
C# | [pgvector-dotnet](https://github.com/pgvector/pgvector-dotnet)
|
C# | [pgvector-dotnet](https://github.com/pgvector/pgvector-dotnet)
|
||||||
Crystal | [pgvector-crystal](https://github.com/pgvector/pgvector-crystal)
|
|
||||||
Elixir | [pgvector-elixir](https://github.com/pgvector/pgvector-elixir)
|
Elixir | [pgvector-elixir](https://github.com/pgvector/pgvector-elixir)
|
||||||
Go | [pgvector-go](https://github.com/pgvector/pgvector-go)
|
Go | [pgvector-go](https://github.com/pgvector/pgvector-go)
|
||||||
Haskell | [pgvector-haskell](https://github.com/pgvector/pgvector-haskell)
|
|
||||||
Java, Scala | [pgvector-java](https://github.com/pgvector/pgvector-java)
|
Java, Scala | [pgvector-java](https://github.com/pgvector/pgvector-java)
|
||||||
Julia | [pgvector-julia](https://github.com/pgvector/pgvector-julia)
|
Julia | [pgvector-julia](https://github.com/pgvector/pgvector-julia)
|
||||||
Lua | [pgvector-lua](https://github.com/pgvector/pgvector-lua)
|
Lua | [pgvector-lua](https://github.com/pgvector/pgvector-lua)
|
||||||
@@ -293,7 +287,6 @@ Python | [pgvector-python](https://github.com/pgvector/pgvector-python)
|
|||||||
R | [pgvector-r](https://github.com/pgvector/pgvector-r)
|
R | [pgvector-r](https://github.com/pgvector/pgvector-r)
|
||||||
Ruby | [pgvector-ruby](https://github.com/pgvector/pgvector-ruby), [Neighbor](https://github.com/ankane/neighbor)
|
Ruby | [pgvector-ruby](https://github.com/pgvector/pgvector-ruby), [Neighbor](https://github.com/ankane/neighbor)
|
||||||
Rust | [pgvector-rust](https://github.com/pgvector/pgvector-rust)
|
Rust | [pgvector-rust](https://github.com/pgvector/pgvector-rust)
|
||||||
Swift | [pgvector-swift](https://github.com/pgvector/pgvector-swift)
|
|
||||||
|
|
||||||
## Frequently Asked Questions
|
## Frequently Asked Questions
|
||||||
|
|
||||||
@@ -312,10 +305,6 @@ Two things you can try are:
|
|||||||
1. use dimensionality reduction
|
1. use dimensionality reduction
|
||||||
2. compile Postgres with a larger block size (`./configure --with-blocksize=32`) and edit the limit in `src/ivfflat.h`
|
2. compile Postgres with a larger block size (`./configure --with-blocksize=32`) and edit the limit in `src/ivfflat.h`
|
||||||
|
|
||||||
#### Why am I seeing less results after adding an index?
|
|
||||||
|
|
||||||
The index was likely created with too little data for the number of lists. Drop the index until the table has more data.
|
|
||||||
|
|
||||||
## Reference
|
## Reference
|
||||||
|
|
||||||
### Vector Type
|
### Vector Type
|
||||||
@@ -452,7 +441,7 @@ To request a new extension on other providers:
|
|||||||
- Google Cloud SQL - vote or comment on [this page](https://issuetracker.google.com/issues/265172065)
|
- Google Cloud SQL - vote or comment on [this page](https://issuetracker.google.com/issues/265172065)
|
||||||
- Azure Database - vote or comment on [this page](https://feedback.azure.com/d365community/idea/7b423322-6189-ed11-a81b-000d3ae49307)
|
- Azure Database - vote or comment on [this page](https://feedback.azure.com/d365community/idea/7b423322-6189-ed11-a81b-000d3ae49307)
|
||||||
- DigitalOcean Managed Databases - vote or comment on [this page](https://ideas.digitalocean.com/app-framework-services/p/pgvector-extension-for-postgresql)
|
- DigitalOcean Managed Databases - vote or comment on [this page](https://ideas.digitalocean.com/app-framework-services/p/pgvector-extension-for-postgresql)
|
||||||
- Heroku Postgres - vote or comment on [this page](https://github.com/heroku/roadmap/issues/156)
|
- Render - vote or comment on [this page](https://feedback.render.com/features/p/add-pgvector-extension-to-postgresql)
|
||||||
|
|
||||||
## Upgrading
|
## Upgrading
|
||||||
|
|
||||||
|
|||||||
@@ -206,7 +206,6 @@ typedef struct IvfflatScanOpaqueData
|
|||||||
|
|
||||||
/* Lists */
|
/* Lists */
|
||||||
pairingheap *listQueue;
|
pairingheap *listQueue;
|
||||||
double minDistance;
|
|
||||||
IvfflatScanList lists[FLEXIBLE_ARRAY_MEMBER]; /* must come last */
|
IvfflatScanList lists[FLEXIBLE_ARRAY_MEMBER]; /* must come last */
|
||||||
} IvfflatScanOpaqueData;
|
} IvfflatScanOpaqueData;
|
||||||
|
|
||||||
|
|||||||
@@ -60,9 +60,6 @@ GetScanLists(IndexScanDesc scan, Datum value)
|
|||||||
/* Use procinfo from the index instead of scan key for performance */
|
/* Use procinfo from the index instead of scan key for performance */
|
||||||
distance = DatumGetFloat8(FunctionCall2Coll(so->procinfo, so->collation, PointerGetDatum(&list->center), value));
|
distance = DatumGetFloat8(FunctionCall2Coll(so->procinfo, so->collation, PointerGetDatum(&list->center), value));
|
||||||
|
|
||||||
if (distance < so->minDistance)
|
|
||||||
so->minDistance = distance;
|
|
||||||
|
|
||||||
if (listCount < so->probes)
|
if (listCount < so->probes)
|
||||||
{
|
{
|
||||||
scanlist = &so->lists[listCount];
|
scanlist = &so->lists[listCount];
|
||||||
@@ -127,18 +124,12 @@ 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);
|
||||||
|
|
||||||
/* Search closest probes lists */
|
/* Search closest probes lists */
|
||||||
while (!pairingheap_is_empty(so->listQueue))
|
while (!pairingheap_is_empty(so->listQueue))
|
||||||
{
|
{
|
||||||
IvfflatScanList *scanlist = (IvfflatScanList *) pairingheap_remove_first(so->listQueue);
|
searchPage = ((IvfflatScanList *) pairingheap_remove_first(so->listQueue))->startPage;
|
||||||
|
|
||||||
/* Query-aware dynamic pruning */
|
|
||||||
if (fabs(scanlist->distance) > 1.5 * fabs(so->minDistance))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
searchPage = scanlist->startPage;
|
|
||||||
|
|
||||||
/* Search all entry pages for list */
|
/* Search all entry pages for list */
|
||||||
while (BlockNumberIsValid(searchPage))
|
while (BlockNumberIsValid(searchPage))
|
||||||
@@ -261,7 +252,6 @@ ivfflatrescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int
|
|||||||
|
|
||||||
so->first = true;
|
so->first = true;
|
||||||
pairingheap_reset(so->listQueue);
|
pairingheap_reset(so->listQueue);
|
||||||
so->minDistance = DBL_MAX;
|
|
||||||
|
|
||||||
if (keys && scan->numberOfKeys > 0)
|
if (keys && scan->numberOfKeys > 0)
|
||||||
memmove(scan->keyData, keys, scan->numberOfKeys * sizeof(ScanKeyData));
|
memmove(scan->keyData, keys, scan->numberOfKeys * sizeof(ScanKeyData));
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ CheckStateArray(ArrayType *statearray, const char *caller)
|
|||||||
return (float8 *) ARR_DATA_PTR(statearray);
|
return (float8 *) ARR_DATA_PTR(statearray);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PG_VERSION_NUM < 120003
|
#if PG_VERSION_NUM < 120000
|
||||||
static pg_noinline void
|
static pg_noinline void
|
||||||
float_overflow_error(void)
|
float_overflow_error(void)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user