mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-22 12:07:34 +08:00
Compare commits
8 Commits
v0.4.0
...
random_vec
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7a0abe6ad | ||
|
|
9b13db5c5c | ||
|
|
ca9d4ed82a | ||
|
|
b1ffe2d4d3 | ||
|
|
246f8814bc | ||
|
|
a5d8bb2688 | ||
|
|
95e496ba00 | ||
|
|
6bfc2cb9a1 |
@@ -1,3 +1,7 @@
|
|||||||
|
## 0.4.1 (unreleased)
|
||||||
|
|
||||||
|
- Added `random_vector` function
|
||||||
|
|
||||||
## 0.4.0 (2023-01-11)
|
## 0.4.0 (2023-01-11)
|
||||||
|
|
||||||
If upgrading with Postgres < 13, see [this note](https://github.com/pgvector/pgvector#040).
|
If upgrading with Postgres < 13, see [this note](https://github.com/pgvector/pgvector#040).
|
||||||
|
|||||||
44
README.md
44
README.md
@@ -29,7 +29,7 @@ Then load it in databases where you want to use it
|
|||||||
CREATE EXTENSION vector;
|
CREATE EXTENSION vector;
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also install it with [Docker](#docker), [Homebrew](#homebrew), or [PGXN](#pgxn)
|
You can also install it with [Docker](#docker), [Homebrew](#homebrew), [PGXN](#pgxn), or [conda-forge](#conda-forge)
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
@@ -184,26 +184,26 @@ inner_product(vector, vector) → double precision | inner product
|
|||||||
l2_distance(vector, vector) → double precision | Euclidean distance
|
l2_distance(vector, vector) → double precision | Euclidean distance
|
||||||
vector_dims(vector) → integer | number of dimensions
|
vector_dims(vector) → integer | number of dimensions
|
||||||
vector_norm(vector) → double precision | Euclidean norm
|
vector_norm(vector) → double precision | Euclidean norm
|
||||||
|
random_vector(integer) → vector | random vector [unreleased]
|
||||||
|
|
||||||
### Aggregate Functions
|
### Aggregate Functions
|
||||||
|
|
||||||
Function | Description | Partial Mode
|
Function | Description
|
||||||
--- | --- | ---
|
--- | ---
|
||||||
avg(vector) → vector | arithmetic mean | Yes
|
avg(vector) → vector | arithmetic mean
|
||||||
|
|
||||||
## Libraries
|
## Libraries
|
||||||
|
|
||||||
Libraries that use pgvector:
|
Language | Libraries
|
||||||
|
--- | ---
|
||||||
- [pgvector-python](https://github.com/pgvector/pgvector-python) (Python)
|
Python | [pgvector-python](https://github.com/pgvector/pgvector-python)
|
||||||
- [Neighbor](https://github.com/ankane/neighbor) (Ruby)
|
Ruby | [Neighbor](https://github.com/ankane/neighbor), [pgvector-ruby](https://github.com/pgvector/pgvector-ruby)
|
||||||
- [pgvector-ruby](https://github.com/pgvector/pgvector-ruby) (Ruby)
|
Node | [pgvector-node](https://github.com/pgvector/pgvector-node)
|
||||||
- [pgvector-node](https://github.com/pgvector/pgvector-node) (Node.js)
|
Go | [pgvector-go](https://github.com/pgvector/pgvector-go)
|
||||||
- [pgvector-go](https://github.com/pgvector/pgvector-go) (Go)
|
PHP | [pgvector-php](https://github.com/pgvector/pgvector-php)
|
||||||
- [pgvector-php](https://github.com/pgvector/pgvector-php) (PHP)
|
Rust | [pgvector-rust](https://github.com/pgvector/pgvector-rust)
|
||||||
- [pgvector-rust](https://github.com/pgvector/pgvector-rust) (Rust)
|
C++ | [pgvector-cpp](https://github.com/pgvector/pgvector-cpp)
|
||||||
- [pgvector-cpp](https://github.com/pgvector/pgvector-cpp) (C++)
|
Elixir | [pgvector-elixir](https://github.com/pgvector/pgvector-elixir)
|
||||||
- [pgvector-elixir](https://github.com/pgvector/pgvector-elixir) (Elixir)
|
|
||||||
|
|
||||||
## Frequently Asked Questions
|
## Frequently Asked Questions
|
||||||
|
|
||||||
@@ -258,12 +258,22 @@ Install from the [PostgreSQL Extension Network](https://pgxn.org/dist/vector) wi
|
|||||||
pgxn install vector
|
pgxn install vector
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### conda-forge
|
||||||
|
|
||||||
|
Install from [conda-forge](https://anaconda.org/conda-forge/pgvector) with:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
conda install -c conda-forge pgvector
|
||||||
|
```
|
||||||
|
|
||||||
|
This method is [community-maintained](https://github.com/conda-forge/pgvector-feedstock) by [@mmcauliffe](https://github.com/mmcauliffe)
|
||||||
|
|
||||||
## Hosted Postgres
|
## Hosted Postgres
|
||||||
|
|
||||||
Some Postgres providers only support specific extensions. To request a new extension:
|
Some Postgres providers only support specific extensions. To request a new extension:
|
||||||
|
|
||||||
- Amazon RDS - follow the instructions on [this page](https://aws.amazon.com/rds/postgresql/faqs/)
|
- 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)
|
- Google Cloud SQL - vote or comment on [this page](https://issuetracker.google.com/issues/265172065)
|
||||||
- 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)
|
||||||
- Azure Database for PostgreSQL - vote or comment on [this page](https://feedback.azure.com/d365community/idea/7b423322-6189-ed11-a81b-000d3ae49307)
|
- Azure Database for PostgreSQL - vote or comment on [this page](https://feedback.azure.com/d365community/idea/7b423322-6189-ed11-a81b-000d3ae49307)
|
||||||
|
|
||||||
@@ -279,7 +289,7 @@ ALTER EXTENSION vector UPDATE;
|
|||||||
|
|
||||||
### 0.4.0
|
### 0.4.0
|
||||||
|
|
||||||
For Postgres < 13, remove this line from `sql/vector--0.3.2--0.4.0.sql`:
|
If upgrading with Postgres < 13, remove this line from `sql/vector--0.3.2--0.4.0.sql`:
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
ALTER TYPE vector SET (STORAGE = extended);
|
ALTER TYPE vector SET (STORAGE = extended);
|
||||||
|
|||||||
5
sql/vector--0.4.0--0.4.1.sql
Normal file
5
sql/vector--0.4.0--0.4.1.sql
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||||
|
\echo Use "ALTER EXTENSION vector UPDATE TO '0.4.1'" to load this file. \quit
|
||||||
|
|
||||||
|
CREATE FUNCTION random_vector(integer) RETURNS vector
|
||||||
|
AS 'MODULE_PATHNAME' LANGUAGE C VOLATILE STRICT PARALLEL SAFE;
|
||||||
@@ -52,6 +52,9 @@ CREATE FUNCTION vector_add(vector, vector) RETURNS vector
|
|||||||
CREATE FUNCTION vector_sub(vector, vector) RETURNS vector
|
CREATE FUNCTION vector_sub(vector, vector) RETURNS vector
|
||||||
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
||||||
|
|
||||||
|
CREATE FUNCTION random_vector(integer) RETURNS vector
|
||||||
|
AS 'MODULE_PATHNAME' LANGUAGE C VOLATILE STRICT PARALLEL SAFE;
|
||||||
|
|
||||||
-- private functions
|
-- private functions
|
||||||
|
|
||||||
CREATE FUNCTION vector_lt(vector, vector) RETURNS bool
|
CREATE FUNCTION vector_lt(vector, vector) RETURNS bool
|
||||||
|
|||||||
@@ -10,15 +10,10 @@
|
|||||||
#include "access/generic_xlog.h"
|
#include "access/generic_xlog.h"
|
||||||
#include "access/reloptions.h"
|
#include "access/reloptions.h"
|
||||||
#include "nodes/execnodes.h"
|
#include "nodes/execnodes.h"
|
||||||
#include "port.h" /* for strtof() and random() */
|
|
||||||
#include "utils/sampling.h"
|
#include "utils/sampling.h"
|
||||||
#include "utils/tuplesort.h"
|
#include "utils/tuplesort.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 150000
|
|
||||||
#include "common/pg_prng.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IVFFLAT_BENCH
|
#ifdef IVFFLAT_BENCH
|
||||||
#include "portability/instr_time.h"
|
#include "portability/instr_time.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -68,14 +63,6 @@
|
|||||||
#define IvfflatBench(name, code) (code)
|
#define IvfflatBench(name, code) (code)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 150000
|
|
||||||
#define RandomDouble() pg_prng_double(&pg_global_prng_state)
|
|
||||||
#define RandomInt() pg_prng_uint32(&pg_global_prng_state)
|
|
||||||
#else
|
|
||||||
#define RandomDouble() (((double) random()) / MAX_RANDOM_VALUE)
|
|
||||||
#define RandomInt() random()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Variables */
|
/* Variables */
|
||||||
extern int ivfflat_probes;
|
extern int ivfflat_probes;
|
||||||
|
|
||||||
|
|||||||
19
src/vector.c
19
src/vector.c
@@ -950,3 +950,22 @@ vector_avg(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate a random vector
|
||||||
|
*/
|
||||||
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(random_vector);
|
||||||
|
Datum
|
||||||
|
random_vector(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
int32 dim = PG_GETARG_INT32(0);
|
||||||
|
Vector *result;
|
||||||
|
|
||||||
|
CheckDim(dim);
|
||||||
|
|
||||||
|
result = InitVector(dim);
|
||||||
|
for (int i = 0; i < dim; i++)
|
||||||
|
result->x[i] = RandomDouble();
|
||||||
|
|
||||||
|
PG_RETURN_POINTER(result);
|
||||||
|
}
|
||||||
|
|||||||
14
src/vector.h
14
src/vector.h
@@ -3,6 +3,12 @@
|
|||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
|
#include "port.h" /* for strtof() and random() */
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= 150000
|
||||||
|
#include "common/pg_prng.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define VECTOR_MAX_DIM 16000
|
#define VECTOR_MAX_DIM 16000
|
||||||
|
|
||||||
#define VECTOR_SIZE(_dim) (offsetof(Vector, x) + sizeof(float)*(_dim))
|
#define VECTOR_SIZE(_dim) (offsetof(Vector, x) + sizeof(float)*(_dim))
|
||||||
@@ -10,6 +16,14 @@
|
|||||||
#define PG_GETARG_VECTOR_P(x) DatumGetVector(PG_GETARG_DATUM(x))
|
#define PG_GETARG_VECTOR_P(x) DatumGetVector(PG_GETARG_DATUM(x))
|
||||||
#define PG_RETURN_VECTOR_P(x) PG_RETURN_POINTER(x)
|
#define PG_RETURN_VECTOR_P(x) PG_RETURN_POINTER(x)
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= 150000
|
||||||
|
#define RandomDouble() pg_prng_double(&pg_global_prng_state)
|
||||||
|
#define RandomInt() pg_prng_uint32(&pg_global_prng_state)
|
||||||
|
#else
|
||||||
|
#define RandomDouble() (((double) random()) / MAX_RANDOM_VALUE)
|
||||||
|
#define RandomInt() random()
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct Vector
|
typedef struct Vector
|
||||||
{
|
{
|
||||||
int32 vl_len_; /* varlena header (do not touch directly!) */
|
int32 vl_len_; /* varlena header (do not touch directly!) */
|
||||||
|
|||||||
@@ -44,11 +44,6 @@ sub test_index_replay
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Use ARRAY[random(), random(), random(), ...] over
|
|
||||||
# SELECT array_agg(random()) FROM generate_series(1, $dim)
|
|
||||||
# to generate different values for each row
|
|
||||||
my $array_sql = join(",", ('random()') x $dim);
|
|
||||||
|
|
||||||
# Initialize primary node
|
# Initialize primary node
|
||||||
$node_primary = get_new_node('primary');
|
$node_primary = get_new_node('primary');
|
||||||
$node_primary->init(allows_streaming => 1);
|
$node_primary->init(allows_streaming => 1);
|
||||||
@@ -75,7 +70,7 @@ $node_replica->start;
|
|||||||
$node_primary->safe_psql("postgres", "CREATE EXTENSION vector;");
|
$node_primary->safe_psql("postgres", "CREATE EXTENSION vector;");
|
||||||
$node_primary->safe_psql("postgres", "CREATE TABLE tst (i int4, v vector($dim));");
|
$node_primary->safe_psql("postgres", "CREATE TABLE tst (i int4, v vector($dim));");
|
||||||
$node_primary->safe_psql("postgres",
|
$node_primary->safe_psql("postgres",
|
||||||
"INSERT INTO tst SELECT i % 10, ARRAY[$array_sql] FROM generate_series(1, 100000) i;"
|
"INSERT INTO tst SELECT i % 10, random_vector($dim) FROM generate_series(1, 100000) i;"
|
||||||
);
|
);
|
||||||
$node_primary->safe_psql("postgres", "CREATE INDEX ON tst USING ivfflat (v);");
|
$node_primary->safe_psql("postgres", "CREATE INDEX ON tst USING ivfflat (v);");
|
||||||
|
|
||||||
@@ -91,7 +86,7 @@ for my $i (1 .. 10)
|
|||||||
test_index_replay("vacuum $i");
|
test_index_replay("vacuum $i");
|
||||||
my ($start, $end) = (100001 + ($i - 1) * 10000, 100000 + $i * 10000);
|
my ($start, $end) = (100001 + ($i - 1) * 10000, 100000 + $i * 10000);
|
||||||
$node_primary->safe_psql("postgres",
|
$node_primary->safe_psql("postgres",
|
||||||
"INSERT INTO tst SELECT i % 10, ARRAY[$array_sql] FROM generate_series($start, $end) i;"
|
"INSERT INTO tst SELECT i % 10, random_vector($dim) FROM generate_series($start, $end) i;"
|
||||||
);
|
);
|
||||||
test_index_replay("insert $i");
|
test_index_replay("insert $i");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ $node->start;
|
|||||||
$node->safe_psql("postgres", "CREATE EXTENSION vector;");
|
$node->safe_psql("postgres", "CREATE EXTENSION vector;");
|
||||||
$node->safe_psql("postgres", "CREATE TABLE tst (i int4, v vector(3));");
|
$node->safe_psql("postgres", "CREATE TABLE tst (i int4, v vector(3));");
|
||||||
$node->safe_psql("postgres",
|
$node->safe_psql("postgres",
|
||||||
"INSERT INTO tst SELECT i, ARRAY[random(), random(), random()] FROM generate_series(1, 100000) i;"
|
"INSERT INTO tst SELECT i, random_vector(3) FROM generate_series(1, 100000) i;"
|
||||||
);
|
);
|
||||||
|
|
||||||
# Generate queries
|
# Generate queries
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ $node->start;
|
|||||||
$node->safe_psql("postgres", "CREATE EXTENSION vector;");
|
$node->safe_psql("postgres", "CREATE EXTENSION vector;");
|
||||||
$node->safe_psql("postgres", "CREATE TABLE tst (i int4 primary key, v vector(3));");
|
$node->safe_psql("postgres", "CREATE TABLE tst (i int4 primary key, v vector(3));");
|
||||||
$node->safe_psql("postgres",
|
$node->safe_psql("postgres",
|
||||||
"INSERT INTO tst SELECT i, ARRAY[random(), random(), random()] FROM generate_series(1, 100000) i;"
|
"INSERT INTO tst SELECT i, random_vector(3) FROM generate_series(1, 100000) i;"
|
||||||
);
|
);
|
||||||
|
|
||||||
# Check each index type
|
# Check each index type
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ $node->start;
|
|||||||
$node->safe_psql("postgres", "CREATE EXTENSION vector;");
|
$node->safe_psql("postgres", "CREATE EXTENSION vector;");
|
||||||
$node->safe_psql("postgres", "CREATE TABLE tst (v vector(3));");
|
$node->safe_psql("postgres", "CREATE TABLE tst (v vector(3));");
|
||||||
$node->safe_psql("postgres",
|
$node->safe_psql("postgres",
|
||||||
"INSERT INTO tst SELECT ARRAY[random(), random(), random()] FROM generate_series(1, 100000) i;"
|
"INSERT INTO tst SELECT random_vector(3) FROM generate_series(1, 100000) i;"
|
||||||
);
|
);
|
||||||
|
|
||||||
$node->safe_psql("postgres", "CREATE INDEX lists50 ON tst USING ivfflat (v) WITH (lists = 50);");
|
$node->safe_psql("postgres", "CREATE INDEX lists50 ON tst USING ivfflat (v) WITH (lists = 50);");
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ use Test::More tests => 5;
|
|||||||
|
|
||||||
my $dim = 768;
|
my $dim = 768;
|
||||||
|
|
||||||
my $array_sql = join(",", ('random()') x $dim);
|
|
||||||
|
|
||||||
# Initialize node
|
# Initialize node
|
||||||
my $node = get_new_node('node');
|
my $node = get_new_node('node');
|
||||||
$node->init;
|
$node->init;
|
||||||
@@ -17,7 +15,7 @@ $node->start;
|
|||||||
$node->safe_psql("postgres", "CREATE EXTENSION vector;");
|
$node->safe_psql("postgres", "CREATE EXTENSION vector;");
|
||||||
$node->safe_psql("postgres", "CREATE TABLE tst (v vector($dim));");
|
$node->safe_psql("postgres", "CREATE TABLE tst (v vector($dim));");
|
||||||
$node->safe_psql("postgres",
|
$node->safe_psql("postgres",
|
||||||
"INSERT INTO tst SELECT ARRAY[$array_sql] FROM generate_series(1, 10000) i;"
|
"INSERT INTO tst SELECT random_vector($dim) FROM generate_series(1, 10000) i;"
|
||||||
);
|
);
|
||||||
$node->safe_psql("postgres", "CREATE INDEX ON tst USING ivfflat (v);");
|
$node->safe_psql("postgres", "CREATE INDEX ON tst USING ivfflat (v);");
|
||||||
|
|
||||||
@@ -28,7 +26,7 @@ $node->pgbench(
|
|||||||
[qr{^$}],
|
[qr{^$}],
|
||||||
"concurrent INSERTs",
|
"concurrent INSERTs",
|
||||||
{
|
{
|
||||||
"007_inserts" => "INSERT INTO tst SELECT ARRAY[$array_sql] FROM generate_series(1, 10) i;"
|
"007_inserts" => "INSERT INTO tst SELECT random_vector($dim) FROM generate_series(1, 10) i;"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ $node->safe_psql("postgres", "CREATE TABLE tst (v1 vector(1024), v2 vector(1024)
|
|||||||
|
|
||||||
# Test insert succeeds
|
# Test insert succeeds
|
||||||
$node->safe_psql("postgres",
|
$node->safe_psql("postgres",
|
||||||
"INSERT INTO tst SELECT array_agg(n), array_agg(n), array_agg(n) FROM generate_series(1, $dim) n"
|
"INSERT INTO tst SELECT random_vector($dim), random_vector($dim), random_vector($dim)"
|
||||||
);
|
);
|
||||||
|
|
||||||
# Change storage to PLAIN
|
# Change storage to PLAIN
|
||||||
@@ -27,6 +27,6 @@ $node->safe_psql("postgres", "ALTER TABLE tst ALTER COLUMN v3 SET STORAGE PLAIN"
|
|||||||
|
|
||||||
# Test insert fails
|
# Test insert fails
|
||||||
my ($ret, $stdout, $stderr) = $node->psql("postgres",
|
my ($ret, $stdout, $stderr) = $node->psql("postgres",
|
||||||
"INSERT INTO tst SELECT array_agg(n), array_agg(n), array_agg(n) FROM generate_series(1, $dim) n"
|
"INSERT INTO tst SELECT random_vector($dim), random_vector($dim), random_vector($dim)"
|
||||||
);
|
);
|
||||||
like($stderr, qr/row is too big/);
|
like($stderr, qr/row is too big/);
|
||||||
|
|||||||
Reference in New Issue
Block a user