mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-22 20:15:46 +08:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea1b094d8e | ||
|
|
63d2965e8e | ||
|
|
e5e7a6ec15 | ||
|
|
ede572d80b | ||
|
|
154e4334fb | ||
|
|
77d54333f6 | ||
|
|
c95732340a | ||
|
|
2af9bdefbb | ||
|
|
bd36231871 | ||
|
|
523788d964 | ||
|
|
1eed57310a | ||
|
|
57e6a01214 | ||
|
|
b713cbc3b6 | ||
|
|
ebeac156c0 | ||
|
|
60bc93f938 | ||
|
|
87a1b3365e | ||
|
|
e9a762223b | ||
|
|
db83f4faa8 | ||
|
|
2cf71ec6bd | ||
|
|
a7510430e3 | ||
|
|
ea8f06e8f4 | ||
|
|
4e0c1a137c | ||
|
|
c758b7b188 | ||
|
|
3dffc01e31 | ||
|
|
b8f3688e41 | ||
|
|
67e317141b | ||
|
|
de2ce0b1eb | ||
|
|
86c1c95ef4 |
8
.dockerignore
Normal file
8
.dockerignore
Normal file
@@ -0,0 +1,8 @@
|
||||
/.git/
|
||||
/dist/
|
||||
/results/
|
||||
/tmp_check/
|
||||
/sql/vector--?.?.?.sql
|
||||
regression.*
|
||||
*.o
|
||||
*.so
|
||||
17
CHANGELOG.md
17
CHANGELOG.md
@@ -1,3 +1,20 @@
|
||||
## 0.1.7 (unreleased)
|
||||
|
||||
- Added cast for `numeric[]`
|
||||
|
||||
## 0.1.6 (2021-06-09)
|
||||
|
||||
- Fixed segmentation fault with `COUNT`
|
||||
|
||||
## 0.1.5 (2021-05-25)
|
||||
|
||||
- Reduced memory usage during index creation
|
||||
|
||||
## 0.1.4 (2021-05-09)
|
||||
|
||||
- Fixed kmeans for inner product
|
||||
- Fixed multiple definition error with GCC 10
|
||||
|
||||
## 0.1.3 (2021-05-06)
|
||||
|
||||
- Added Dockerfile
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "vector",
|
||||
"abstract": "Open-source vector similarity search for Postgres",
|
||||
"description": "Supports L2 distance, inner product, and cosine distance",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.7",
|
||||
"maintainer": [
|
||||
"Andrew Kane <andrew@ankane.org>"
|
||||
],
|
||||
@@ -20,7 +20,7 @@
|
||||
"vector": {
|
||||
"file": "sql/vector.sql",
|
||||
"docfile": "README.md",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.7",
|
||||
"abstract": "Open-source vector similarity search for Postgres"
|
||||
}
|
||||
},
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,5 +1,5 @@
|
||||
EXTENSION = vector
|
||||
EXTVERSION = 0.1.3
|
||||
EXTVERSION = 0.1.7
|
||||
|
||||
MODULE_big = vector
|
||||
DATA = $(wildcard sql/*--*.sql)
|
||||
|
||||
15
README.md
15
README.md
@@ -17,7 +17,7 @@ Supports L2 distance, inner product, and cosine distance
|
||||
Compile and install the extension (supports Postgres 9.6+)
|
||||
|
||||
```sh
|
||||
git clone --branch v0.1.3 https://github.com/ankane/pgvector.git
|
||||
git clone --branch v0.1.7 https://github.com/ankane/pgvector.git
|
||||
cd pgvector
|
||||
make
|
||||
make install # may need sudo
|
||||
@@ -136,7 +136,9 @@ vector_norm(vector) | Euclidean norm
|
||||
|
||||
Libraries that use pgvector:
|
||||
|
||||
- [pgvector-python](https://github.com/ankane/pgvector-python) (Python)
|
||||
- [Neighbor](https://github.com/ankane/neighbor) (Ruby)
|
||||
- [pgvector-rust](https://github.com/ankane/pgvector-rust) (Rust)
|
||||
|
||||
## Additional Installation Methods
|
||||
|
||||
@@ -153,7 +155,7 @@ This adds pgvector to the [Postgres image](https://hub.docker.com/_/postgres).
|
||||
You can also build the image manually
|
||||
|
||||
```sh
|
||||
git clone --branch v0.1.3 https://github.com/ankane/pgvector.git
|
||||
git clone --branch v0.1.7 https://github.com/ankane/pgvector.git
|
||||
cd pgvector
|
||||
docker build -t pgvector .
|
||||
```
|
||||
@@ -181,15 +183,14 @@ Some Postgres providers only support specific extensions. To request a new exten
|
||||
- Amazon RDS - follow the instructions on [this page](https://aws.amazon.com/rds/postgresql/faqs/)
|
||||
- Google Cloud SQL - follow the instructions on [this page](https://cloud.google.com/sql/docs/postgres/extensions#requesting-support-for-a-new-extension)
|
||||
- DigitalOcean Managed Databases - follow the instructions on [this page](https://docs.digitalocean.com/products/databases/postgresql/resources/supported-extensions/#supported-extensions)
|
||||
- Azure Database for PostgreSQL - follow the instructions on [this page](https://docs.microsoft.com/en-us/azure/postgresql/concepts-extensions#next-steps)
|
||||
|
||||
## Upgrading
|
||||
|
||||
### 0.1.1
|
||||
|
||||
Compile and install the latest version and run:
|
||||
Install the latest version and run:
|
||||
|
||||
```sql
|
||||
ALTER EXTENSION vector UPDATE TO '0.1.1';
|
||||
ALTER EXTENSION vector UPDATE;
|
||||
```
|
||||
|
||||
## Thanks
|
||||
@@ -234,7 +235,7 @@ make prove_installcheck # TAP tests
|
||||
To run single tests:
|
||||
|
||||
```sh
|
||||
make installcheck REGRESS=vector # regression test
|
||||
make installcheck REGRESS=functions # regression test
|
||||
make prove_installcheck PROVE_TESTS=test/t/001_wal.pl # TAP test
|
||||
```
|
||||
|
||||
|
||||
2
sql/vector--0.1.3--0.1.4.sql
Normal file
2
sql/vector--0.1.3--0.1.4.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION vector UPDATE TO '0.1.4'" to load this file. \quit
|
||||
2
sql/vector--0.1.4--0.1.5.sql
Normal file
2
sql/vector--0.1.4--0.1.5.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION vector UPDATE TO '0.1.5'" to load this file. \quit
|
||||
2
sql/vector--0.1.5--0.1.6.sql
Normal file
2
sql/vector--0.1.5--0.1.6.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION vector UPDATE TO '0.1.6'" to load this file. \quit
|
||||
8
sql/vector--0.1.6--0.1.7.sql
Normal file
8
sql/vector--0.1.6--0.1.7.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION vector UPDATE TO '0.1.7'" to load this file. \quit
|
||||
|
||||
CREATE FUNCTION array_to_vector(numeric[], integer, boolean) RETURNS vector
|
||||
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
||||
|
||||
CREATE CAST (numeric[] AS vector)
|
||||
WITH FUNCTION array_to_vector(numeric[], integer, boolean) AS IMPLICIT;
|
||||
@@ -97,6 +97,9 @@ CREATE FUNCTION array_to_vector(real[], integer, boolean) RETURNS vector
|
||||
CREATE FUNCTION array_to_vector(double precision[], integer, boolean) RETURNS vector
|
||||
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
||||
|
||||
CREATE FUNCTION array_to_vector(numeric[], integer, boolean) RETURNS vector
|
||||
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
||||
|
||||
-- casts
|
||||
|
||||
CREATE CAST (vector AS vector)
|
||||
@@ -111,6 +114,9 @@ CREATE CAST (real[] AS vector)
|
||||
CREATE CAST (double precision[] AS vector)
|
||||
WITH FUNCTION array_to_vector(double precision[], integer, boolean) AS IMPLICIT;
|
||||
|
||||
CREATE CAST (numeric[] AS vector)
|
||||
WITH FUNCTION array_to_vector(numeric[], integer, boolean) AS IMPLICIT;
|
||||
|
||||
-- operators
|
||||
|
||||
CREATE OPERATOR <-> (
|
||||
|
||||
@@ -41,10 +41,13 @@ SampleCallback(Relation index, CALLBACK_ITEM_POINTER, Datum *values,
|
||||
if (isnull[0])
|
||||
return;
|
||||
|
||||
/* Normalize the value */
|
||||
if (buildstate->normprocinfo != NULL)
|
||||
/*
|
||||
* Normalize with KMEANS_NORM_PROC since spherical distance function
|
||||
* expects unit vectors
|
||||
*/
|
||||
if (buildstate->kmeansnormprocinfo != NULL)
|
||||
{
|
||||
if (!IvfflatNormValue(buildstate->normprocinfo, buildstate->collation, &value, buildstate->normvec))
|
||||
if (!IvfflatNormValue(buildstate->kmeansnormprocinfo, buildstate->collation, &value, buildstate->normvec))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -238,6 +241,8 @@ InsertTuples(Relation index, IvfflatBuildState * buildstate, ForkNumber forkNum)
|
||||
if (PageAddItem(page, (Item) itup, itemsz, InvalidOffsetNumber, false, false) == InvalidOffsetNumber)
|
||||
elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index));
|
||||
|
||||
pfree(itup);
|
||||
|
||||
buildstate->indtuples += 1;
|
||||
|
||||
GetNextTuple(buildstate->sortstate, tupdesc, slot, &itup, &list);
|
||||
@@ -275,6 +280,7 @@ InitBuildState(IvfflatBuildState * buildstate, Relation heap, Relation index, In
|
||||
/* Get support functions */
|
||||
buildstate->procinfo = index_getprocinfo(index, 1, IVFFLAT_DISTANCE_PROC);
|
||||
buildstate->normprocinfo = IvfflatOptionalProcInfo(index, IVFFLAT_NORM_PROC);
|
||||
buildstate->kmeansnormprocinfo = IvfflatOptionalProcInfo(index, IVFFLAT_KMEANS_NORM_PROC);
|
||||
buildstate->collation = index->rd_indcollation[0];
|
||||
|
||||
/* Create tuple description for sorting */
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include "access/amapi.h"
|
||||
#include "commands/vacuum.h"
|
||||
#include "ivfflat.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/selfuncs.h"
|
||||
|
||||
int ivfflat_probes;
|
||||
static relopt_kind ivfflat_relopt_kind;
|
||||
|
||||
/*
|
||||
@@ -43,18 +46,29 @@ ivfflatcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
|
||||
int lists;
|
||||
double ratio;
|
||||
Relation indexRel;
|
||||
|
||||
#if PG_VERSION_NUM < 120000
|
||||
List *qinfos;
|
||||
|
||||
qinfos = deconstruct_indexquals(path);
|
||||
#endif
|
||||
|
||||
/* Never use index without order */
|
||||
if (path->indexorderbys == NULL)
|
||||
{
|
||||
*indexStartupCost = DBL_MAX;
|
||||
*indexTotalCost = DBL_MAX;
|
||||
*indexSelectivity = 0;
|
||||
*indexCorrelation = 0;
|
||||
#if PG_VERSION_NUM >= 100000
|
||||
*indexPages = 0;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
MemSet(&costs, 0, sizeof(costs));
|
||||
|
||||
#if PG_VERSION_NUM >= 120000
|
||||
genericcostestimate(root, path, loop_count, &costs);
|
||||
#else
|
||||
qinfos = deconstruct_indexquals(path);
|
||||
genericcostestimate(root, path, loop_count, qinfos, &costs);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#endif
|
||||
|
||||
/* Variables */
|
||||
int ivfflat_probes;
|
||||
extern int ivfflat_probes;
|
||||
|
||||
typedef struct VectorArrayData
|
||||
{
|
||||
@@ -81,6 +81,7 @@ typedef struct IvfflatBuildState
|
||||
/* Support functions */
|
||||
FmgrInfo *procinfo;
|
||||
FmgrInfo *normprocinfo;
|
||||
FmgrInfo *kmeansnormprocinfo;
|
||||
Oid collation;
|
||||
|
||||
/* Variables */
|
||||
|
||||
@@ -251,6 +251,10 @@ ivfflatgettuple(IndexScanDesc scan, ScanDirection dir)
|
||||
{
|
||||
Datum value;
|
||||
|
||||
/* Safety check */
|
||||
if (scan->orderByData == NULL)
|
||||
elog(ERROR, "cannot scan ivfflat index without order");
|
||||
|
||||
/* No items will match if null */
|
||||
if (scan->orderByData->sk_flags & SK_ISNULL)
|
||||
return false;
|
||||
|
||||
11
src/vector.c
11
src/vector.c
@@ -10,6 +10,7 @@
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/numeric.h"
|
||||
|
||||
#if PG_VERSION_NUM >= 120000
|
||||
#include "utils/float.h"
|
||||
@@ -244,14 +245,20 @@ vector_recv(PG_FUNCTION_ARGS)
|
||||
int32 typmod = PG_GETARG_INT32(2);
|
||||
Vector *result;
|
||||
int16 dim;
|
||||
int16 unused;
|
||||
int i;
|
||||
|
||||
dim = pq_getmsgint(buf, sizeof(int16));
|
||||
pq_getmsgint(buf, sizeof(int16)); /* unused */
|
||||
unused = pq_getmsgint(buf, sizeof(int16));
|
||||
|
||||
CheckDim(dim);
|
||||
CheckExpectedDim(typmod, dim);
|
||||
|
||||
if (unused != 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
||||
errmsg("expected unused to be 0, not %d", unused)));
|
||||
|
||||
result = InitVector(dim);
|
||||
for (i = 0; i < dim; i++)
|
||||
result->x[i] = pq_getmsgfloat4(buf);
|
||||
@@ -339,6 +346,8 @@ array_to_vector(PG_FUNCTION_ARGS)
|
||||
result->x[i] = DatumGetFloat8(elemsp[i]);
|
||||
else if (ARR_ELEMTYPE(array) == FLOAT4OID)
|
||||
result->x[i] = DatumGetFloat4(elemsp[i]);
|
||||
else if (ARR_ELEMTYPE(array) == NUMERICOID)
|
||||
result->x[i] = DatumGetFloat4(DirectFunctionCall1(numeric_float4, NumericGetDatum(elemsp[i])));
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
||||
|
||||
@@ -6,6 +6,12 @@ SELECT ARRAY[1,2,3]::vector;
|
||||
[1,2,3]
|
||||
(1 row)
|
||||
|
||||
SELECT ARRAY[1.0,2.0,3.0]::vector;
|
||||
array
|
||||
---------
|
||||
[1,2,3]
|
||||
(1 row)
|
||||
|
||||
SELECT ARRAY[1,2,3]::float4[]::vector;
|
||||
array
|
||||
---------
|
||||
@@ -28,3 +34,5 @@ SELECT '{-Infinity}'::real[]::vector;
|
||||
ERROR: infinite value not allowed in vector
|
||||
SELECT '{}'::real[]::vector;
|
||||
ERROR: vector must have at least 1 dimension
|
||||
SELECT array_agg(n)::vector FROM generate_series(1, 1025) n;
|
||||
ERROR: vector cannot have more than 1024 dimensions
|
||||
|
||||
@@ -19,4 +19,10 @@ SELECT * FROM t ORDER BY val <-> (SELECT NULL::vector);
|
||||
-----
|
||||
(0 rows)
|
||||
|
||||
SELECT COUNT(*) FROM t;
|
||||
count
|
||||
-------
|
||||
5
|
||||
(1 row)
|
||||
|
||||
DROP TABLE t;
|
||||
|
||||
@@ -2,6 +2,7 @@ SET client_min_messages = warning;
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
|
||||
SELECT ARRAY[1,2,3]::vector;
|
||||
SELECT ARRAY[1.0,2.0,3.0]::vector;
|
||||
SELECT ARRAY[1,2,3]::float4[]::vector;
|
||||
SELECT ARRAY[1,2,3]::float8[]::vector;
|
||||
SELECT '{NULL}'::real[]::vector;
|
||||
@@ -9,3 +10,4 @@ SELECT '{NaN}'::real[]::vector;
|
||||
SELECT '{Infinity}'::real[]::vector;
|
||||
SELECT '{-Infinity}'::real[]::vector;
|
||||
SELECT '{}'::real[]::vector;
|
||||
SELECT array_agg(n)::vector FROM generate_series(1, 1025) n;
|
||||
|
||||
@@ -10,5 +10,6 @@ INSERT INTO t (val) VALUES ('[1,2,4]');
|
||||
|
||||
SELECT * FROM t ORDER BY val <-> '[3,3,3]';
|
||||
SELECT * FROM t ORDER BY val <-> (SELECT NULL::vector);
|
||||
SELECT COUNT(*) FROM t;
|
||||
|
||||
DROP TABLE t;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
comment = 'vector data type and ivfflat access method'
|
||||
default_version = '0.1.3'
|
||||
default_version = '0.1.7'
|
||||
module_pathname = '$libdir/vector'
|
||||
relocatable = true
|
||||
|
||||
Reference in New Issue
Block a user