mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-22 03:57:34 +08:00
Compare commits
26 Commits
neon-intri
...
v0.7.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b89bed701 | ||
|
|
ad7cad5ecd | ||
|
|
2a8b9d689e | ||
|
|
18cd8a60c3 | ||
|
|
8c91a9f56a | ||
|
|
9249e7e2de | ||
|
|
9e91af5989 | ||
|
|
9dcf1bdc80 | ||
|
|
0eceaa3966 | ||
|
|
49c1f13095 | ||
|
|
ff9b22977e | ||
|
|
0468cbf6e6 | ||
|
|
258eaf58fd | ||
|
|
fa8d2df1cc | ||
|
|
69f49290fb | ||
|
|
ad91451266 | ||
|
|
cafd2f6641 | ||
|
|
7923c44efe | ||
|
|
9b269e2612 | ||
|
|
9894ca3e4e | ||
|
|
19cbbfdd69 | ||
|
|
24c8a2ff40 | ||
|
|
6df583a6f6 | ||
|
|
999a2e53dd | ||
|
|
3849f0fd3d | ||
|
|
df178472d1 |
13
CHANGELOG.md
13
CHANGELOG.md
@@ -1,4 +1,15 @@
|
||||
## 0.7.0 (unreleased)
|
||||
## 0.7.2 (2024-06-11)
|
||||
|
||||
- Fixed initialization fork for indexes on unlogged tables
|
||||
|
||||
## 0.7.1 (2024-06-03)
|
||||
|
||||
- Improved performance of on-disk HNSW index builds
|
||||
- Fixed `undefined symbol` error with GCC 8
|
||||
- Fixed compilation error with universal binaries on Mac
|
||||
- Fixed compilation warning with Clang < 14
|
||||
|
||||
## 0.7.0 (2024-04-29)
|
||||
|
||||
- Added `halfvec` type
|
||||
- Added `sparsevec` type
|
||||
|
||||
@@ -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.6.2",
|
||||
"version": "0.7.2",
|
||||
"maintainer": [
|
||||
"Andrew Kane <andrew@ankane.org>"
|
||||
],
|
||||
@@ -20,7 +20,7 @@
|
||||
"vector": {
|
||||
"file": "sql/vector.sql",
|
||||
"docfile": "README.md",
|
||||
"version": "0.6.2",
|
||||
"version": "0.7.2",
|
||||
"abstract": "Open-source vector similarity search for Postgres"
|
||||
}
|
||||
},
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,5 +1,5 @@
|
||||
EXTENSION = vector
|
||||
EXTVERSION = 0.6.2
|
||||
EXTVERSION = 0.7.2
|
||||
|
||||
MODULE_big = vector
|
||||
DATA = $(wildcard sql/*--*.sql)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
EXTENSION = vector
|
||||
EXTVERSION = 0.6.2
|
||||
EXTVERSION = 0.7.2
|
||||
|
||||
OBJS = src\bitutils.obj src\bitvec.obj src\halfutils.obj src\halfvec.obj src\hnsw.obj src\hnswbuild.obj src\hnswinsert.obj src\hnswscan.obj src\hnswutils.obj src\hnswvacuum.obj src\ivfbuild.obj src\ivfflat.obj src\ivfinsert.obj src\ivfkmeans.obj src\ivfscan.obj src\ivfutils.obj src\ivfvacuum.obj src\sparsevec.obj src\vector.obj
|
||||
HEADERS = src\halfvec.h src\sparsevec.h src\vector.h
|
||||
|
||||
REGRESS = bit btree cast copy halfvec hnsw_bit hnsw_halfvec hnsw_sparsevec hnsw_vector ivfflat_bit ivfflat_halfvec ivfflat_vector sparsevec vector
|
||||
REGRESS = bit btree cast copy halfvec hnsw_bit hnsw_halfvec hnsw_sparsevec hnsw_vector ivfflat_bit ivfflat_halfvec ivfflat_vector sparsevec vector_type
|
||||
REGRESS_OPTS = --inputdir=test --load-extension=$(EXTENSION)
|
||||
|
||||
# For /arch flags
|
||||
|
||||
147
README.md
147
README.md
@@ -5,7 +5,8 @@ Open-source vector similarity search for Postgres
|
||||
Store your vectors with the rest of your data. Supports:
|
||||
|
||||
- exact and approximate nearest neighbor search
|
||||
- L2 distance, inner product, and cosine distance
|
||||
- single-precision, half-precision, binary, and sparse vectors
|
||||
- L2 distance, inner product, cosine distance, L1 distance, Hamming distance, and Jaccard distance
|
||||
- any [language](#languages) with a Postgres client
|
||||
|
||||
Plus [ACID](https://en.wikipedia.org/wiki/ACID) compliance, point-in-time recovery, JOINs, and all of the other [great features](https://www.postgresql.org/about/) of Postgres
|
||||
@@ -20,7 +21,7 @@ Compile and install the extension (supports Postgres 12+)
|
||||
|
||||
```sh
|
||||
cd /tmp
|
||||
git clone --branch v0.6.2 https://github.com/pgvector/pgvector.git
|
||||
git clone --branch v0.7.2 https://github.com/pgvector/pgvector.git
|
||||
cd pgvector
|
||||
make
|
||||
make install # may need sudo
|
||||
@@ -45,7 +46,7 @@ Then use `nmake` to build:
|
||||
```cmd
|
||||
set "PGROOT=C:\Program Files\PostgreSQL\16"
|
||||
cd %TEMP%
|
||||
git clone --branch v0.6.2 https://github.com/pgvector/pgvector.git
|
||||
git clone --branch v0.7.2 https://github.com/pgvector/pgvector.git
|
||||
cd pgvector
|
||||
nmake /F Makefile.win
|
||||
nmake /F Makefile.win install
|
||||
@@ -81,7 +82,7 @@ Get the nearest neighbors by L2 distance
|
||||
SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;
|
||||
```
|
||||
|
||||
Also supports inner product (`<#>`), cosine distance (`<=>`), and L1 distance (`<+>`, unreleased)
|
||||
Also supports inner product (`<#>`), cosine distance (`<=>`), and L1 distance (`<+>`, added in 0.7.0)
|
||||
|
||||
Note: `<#>` returns the negative inner product since Postgres only supports `ASC` order index scans on operators
|
||||
|
||||
@@ -143,7 +144,7 @@ Supported distance functions are:
|
||||
- `<->` - L2 distance
|
||||
- `<#>` - (negative) inner product
|
||||
- `<=>` - cosine distance
|
||||
- `<+>` - L1 distance (unreleased)
|
||||
- `<+>` - L1 distance (added in 0.7.0)
|
||||
|
||||
Get the nearest neighbors to a row
|
||||
|
||||
@@ -216,6 +217,8 @@ L2 distance
|
||||
CREATE INDEX ON items USING hnsw (embedding vector_l2_ops);
|
||||
```
|
||||
|
||||
Note: Use `halfvec_l2_ops` for `halfvec` and `sparsevec_l2_ops` for `sparsevec` (and similar with the other distance functions)
|
||||
|
||||
Inner product
|
||||
|
||||
```sql
|
||||
@@ -228,19 +231,19 @@ Cosine distance
|
||||
CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops);
|
||||
```
|
||||
|
||||
L1 distance - unreleased
|
||||
L1 distance - added in 0.7.0
|
||||
|
||||
```sql
|
||||
CREATE INDEX ON items USING hnsw (embedding vector_l1_ops);
|
||||
```
|
||||
|
||||
Hamming distance - unreleased
|
||||
Hamming distance - added in 0.7.0
|
||||
|
||||
```sql
|
||||
CREATE INDEX ON items USING hnsw (embedding bit_hamming_ops);
|
||||
```
|
||||
|
||||
Jaccard distance - unreleased
|
||||
Jaccard distance - added in 0.7.0
|
||||
|
||||
```sql
|
||||
CREATE INDEX ON items USING hnsw (embedding bit_jaccard_ops);
|
||||
@@ -249,9 +252,9 @@ CREATE INDEX ON items USING hnsw (embedding bit_jaccard_ops);
|
||||
Supported types are:
|
||||
|
||||
- `vector` - up to 2,000 dimensions
|
||||
- `halfvec` - up to 4,000 dimensions (unreleased)
|
||||
- `bit` - up to 64,000 dimensions (unreleased)
|
||||
- `sparsevec` - up to 1,000 non-zero elements (unreleased)
|
||||
- `halfvec` - up to 4,000 dimensions (added in 0.7.0)
|
||||
- `bit` - up to 64,000 dimensions (added in 0.7.0)
|
||||
- `sparsevec` - up to 1,000 non-zero elements (added in 0.7.0)
|
||||
|
||||
### Index Options
|
||||
|
||||
@@ -344,6 +347,8 @@ L2 distance
|
||||
CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100);
|
||||
```
|
||||
|
||||
Note: Use `halfvec_l2_ops` for `halfvec` (and similar with the other distance functions)
|
||||
|
||||
Inner product
|
||||
|
||||
```sql
|
||||
@@ -356,7 +361,7 @@ Cosine distance
|
||||
CREATE INDEX ON items USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
|
||||
```
|
||||
|
||||
Hamming distance - unreleased
|
||||
Hamming distance - added in 0.7.0
|
||||
|
||||
```sql
|
||||
CREATE INDEX ON items USING ivfflat (embedding bit_hamming_ops) WITH (lists = 100);
|
||||
@@ -365,8 +370,8 @@ CREATE INDEX ON items USING ivfflat (embedding bit_hamming_ops) WITH (lists = 10
|
||||
Supported types are:
|
||||
|
||||
- `vector` - up to 2,000 dimensions
|
||||
- `halfvec` - up to 4,000 dimensions (unreleased)
|
||||
- `bit` - up to 64,000 dimensions (unreleased)
|
||||
- `halfvec` - up to 4,000 dimensions (added in 0.7.0)
|
||||
- `bit` - up to 64,000 dimensions (added in 0.7.0)
|
||||
|
||||
### Query Options
|
||||
|
||||
@@ -440,9 +445,9 @@ Use [partitioning](https://www.postgresql.org/docs/current/ddl-partitioning.html
|
||||
CREATE TABLE items (embedding vector(3), category_id int) PARTITION BY LIST(category_id);
|
||||
```
|
||||
|
||||
## Half Vectors
|
||||
## Half-Precision Vectors
|
||||
|
||||
*Unreleased*
|
||||
*Added in 0.7.0*
|
||||
|
||||
Use the `halfvec` type to store half-precision vectors
|
||||
|
||||
@@ -450,11 +455,11 @@ Use the `halfvec` type to store half-precision vectors
|
||||
CREATE TABLE items (id bigserial PRIMARY KEY, embedding halfvec(3));
|
||||
```
|
||||
|
||||
## Half Indexing
|
||||
## Half-Precision Indexing
|
||||
|
||||
*Unreleased*
|
||||
*Added in 0.7.0*
|
||||
|
||||
Index vectors at half precision for smaller indexes and faster build times
|
||||
Index vectors at half precision for smaller indexes
|
||||
|
||||
```sql
|
||||
CREATE INDEX ON items USING hnsw ((embedding::halfvec(3)) halfvec_l2_ops);
|
||||
@@ -475,23 +480,23 @@ CREATE TABLE items (id bigserial PRIMARY KEY, embedding bit(3));
|
||||
INSERT INTO items (embedding) VALUES ('000'), ('111');
|
||||
```
|
||||
|
||||
Get the nearest neighbors by Hamming distance
|
||||
|
||||
```sql
|
||||
SELECT * FROM items ORDER BY bit_count(embedding # '101') LIMIT 5;
|
||||
```
|
||||
|
||||
Or (unreleased)
|
||||
Get the nearest neighbors by Hamming distance (added in 0.7.0)
|
||||
|
||||
```sql
|
||||
SELECT * FROM items ORDER BY embedding <~> '101' LIMIT 5;
|
||||
```
|
||||
|
||||
Or (before 0.7.0)
|
||||
|
||||
```sql
|
||||
SELECT * FROM items ORDER BY bit_count(embedding # '101') LIMIT 5;
|
||||
```
|
||||
|
||||
Also supports Jaccard distance (`<%>`)
|
||||
|
||||
## Binary Quantization
|
||||
|
||||
*Unreleased*
|
||||
*Added in 0.7.0*
|
||||
|
||||
Use expression indexing for binary quantization
|
||||
|
||||
@@ -515,7 +520,7 @@ SELECT * FROM (
|
||||
|
||||
## Sparse Vectors
|
||||
|
||||
*Unreleased*
|
||||
*Added in 0.7.0*
|
||||
|
||||
Use the `sparsevec` type to store sparse vectors
|
||||
|
||||
@@ -550,7 +555,7 @@ You can use [Reciprocal Rank Fusion](https://github.com/pgvector/pgvector-python
|
||||
|
||||
## Indexing Subvectors
|
||||
|
||||
*Unreleased*
|
||||
*Added in 0.7.0*
|
||||
|
||||
Use expression indexing to index subvectors
|
||||
|
||||
@@ -726,7 +731,7 @@ Yes, pgvector uses the write-ahead log (WAL), which allows for replication and p
|
||||
|
||||
#### What if I want to index vectors with more than 2,000 dimensions?
|
||||
|
||||
You’ll need to use [dimensionality reduction](https://en.wikipedia.org/wiki/Dimensionality_reduction) at the moment.
|
||||
You can use [half-precision indexing](#half-precision-indexing) to index up to 4,000 dimensions or [binary quantization](#binary-quantization) to index up to 64,000 dimensions. Another option is [dimensionality reduction](https://en.wikipedia.org/wiki/Dimensionality_reduction).
|
||||
|
||||
#### Can I store vectors with different dimensions in the same column?
|
||||
|
||||
@@ -789,7 +794,7 @@ SELECT pg_size_pretty(pg_relation_size('index_name'));
|
||||
|
||||
#### Why isn’t a query using an index?
|
||||
|
||||
The query needs to have an `ORDER BY` and `LIMIT`, and the `ORDER BY` must be the result of a distance operator, not an expression.
|
||||
The query needs to have an `ORDER BY` and `LIMIT`, and the `ORDER BY` must be the result of a distance operator (not an expression) in ascending order.
|
||||
|
||||
```sql
|
||||
-- index
|
||||
@@ -864,23 +869,23 @@ Operator | Description | Added
|
||||
\+ | element-wise addition |
|
||||
\- | element-wise subtraction |
|
||||
\* | element-wise multiplication | 0.5.0
|
||||
\|\| | concatenate | unreleased
|
||||
\|\| | concatenate | 0.7.0
|
||||
<-> | Euclidean distance |
|
||||
<#> | negative inner product |
|
||||
<=> | cosine distance |
|
||||
<+> | taxicab distance | unreleased
|
||||
<+> | taxicab distance | 0.7.0
|
||||
|
||||
### Vector Functions
|
||||
|
||||
Function | Description | Added
|
||||
--- | --- | ---
|
||||
binary_quantize(vector) → bit | binary quantize | unreleased
|
||||
binary_quantize(vector) → bit | binary quantize | 0.7.0
|
||||
cosine_distance(vector, vector) → double precision | cosine distance |
|
||||
inner_product(vector, vector) → double precision | inner product |
|
||||
l1_distance(vector, vector) → double precision | taxicab distance | 0.5.0
|
||||
l2_distance(vector, vector) → double precision | Euclidean distance |
|
||||
l2_normalize(vector) → vector | Normalize with Euclidean norm | unreleased
|
||||
subvector(vector, integer, integer) → vector | subvector | unreleased
|
||||
l2_normalize(vector) → vector | Normalize with Euclidean norm | 0.7.0
|
||||
subvector(vector, integer, integer) → vector | subvector | 0.7.0
|
||||
vector_dims(vector) → integer | number of dimensions |
|
||||
vector_norm(vector) → double precision | Euclidean norm |
|
||||
|
||||
@@ -899,35 +904,35 @@ Each half vector takes `2 * dimensions + 8` bytes of storage. Each element is a
|
||||
|
||||
Operator | Description | Added
|
||||
--- | --- | ---
|
||||
\+ | element-wise addition | unreleased
|
||||
\- | element-wise subtraction | unreleased
|
||||
\* | element-wise multiplication | unreleased
|
||||
\|\| | concatenate | unreleased
|
||||
<-> | Euclidean distance | unreleased
|
||||
<#> | negative inner product | unreleased
|
||||
<=> | cosine distance | unreleased
|
||||
<+> | taxicab distance | unreleased
|
||||
\+ | element-wise addition | 0.7.0
|
||||
\- | element-wise subtraction | 0.7.0
|
||||
\* | element-wise multiplication | 0.7.0
|
||||
\|\| | concatenate | 0.7.0
|
||||
<-> | Euclidean distance | 0.7.0
|
||||
<#> | negative inner product | 0.7.0
|
||||
<=> | cosine distance | 0.7.0
|
||||
<+> | taxicab distance | 0.7.0
|
||||
|
||||
### Halfvec Functions
|
||||
|
||||
Function | Description | Added
|
||||
--- | --- | ---
|
||||
binary_quantize(halfvec) → bit | binary quantize | unreleased
|
||||
cosine_distance(halfvec, halfvec) → double precision | cosine distance | unreleased
|
||||
inner_product(halfvec, halfvec) → double precision | inner product | unreleased
|
||||
l1_distance(halfvec, halfvec) → double precision | taxicab distance | unreleased
|
||||
l2_distance(halfvec, halfvec) → double precision | Euclidean distance | unreleased
|
||||
l2_norm(halfvec) → double precision | Euclidean norm | unreleased
|
||||
l2_normalize(halfvec) → halfvec | Normalize with Euclidean norm | unreleased
|
||||
subvector(halfvec, integer, integer) → halfvec | subvector | unreleased
|
||||
vector_dims(halfvec) → integer | number of dimensions | unreleased
|
||||
binary_quantize(halfvec) → bit | binary quantize | 0.7.0
|
||||
cosine_distance(halfvec, halfvec) → double precision | cosine distance | 0.7.0
|
||||
inner_product(halfvec, halfvec) → double precision | inner product | 0.7.0
|
||||
l1_distance(halfvec, halfvec) → double precision | taxicab distance | 0.7.0
|
||||
l2_distance(halfvec, halfvec) → double precision | Euclidean distance | 0.7.0
|
||||
l2_norm(halfvec) → double precision | Euclidean norm | 0.7.0
|
||||
l2_normalize(halfvec) → halfvec | Normalize with Euclidean norm | 0.7.0
|
||||
subvector(halfvec, integer, integer) → halfvec | subvector | 0.7.0
|
||||
vector_dims(halfvec) → integer | number of dimensions | 0.7.0
|
||||
|
||||
### Halfvec Aggregate Functions
|
||||
|
||||
Function | Description | Added
|
||||
--- | --- | ---
|
||||
avg(halfvec) → halfvec | average | unreleased
|
||||
sum(halfvec) → halfvec | sum | unreleased
|
||||
avg(halfvec) → halfvec | average | 0.7.0
|
||||
sum(halfvec) → halfvec | sum | 0.7.0
|
||||
|
||||
### Bit Type
|
||||
|
||||
@@ -937,15 +942,15 @@ Each bit vector takes `dimensions / 8 + 8` bytes of storage. See the [Postgres d
|
||||
|
||||
Operator | Description | Added
|
||||
--- | --- | ---
|
||||
<~> | Hamming distance | unreleased
|
||||
<%> | Jaccard distance | unreleased
|
||||
<~> | Hamming distance | 0.7.0
|
||||
<%> | Jaccard distance | 0.7.0
|
||||
|
||||
### Bit Functions
|
||||
|
||||
Function | Description | Added
|
||||
--- | --- | ---
|
||||
hamming_distance(bit, bit) → double precision | Hamming distance | unreleased
|
||||
jaccard_distance(bit, bit) → double precision | Jaccard distance | unreleased
|
||||
hamming_distance(bit, bit) → double precision | Hamming distance | 0.7.0
|
||||
jaccard_distance(bit, bit) → double precision | Jaccard distance | 0.7.0
|
||||
|
||||
### Sparsevec Type
|
||||
|
||||
@@ -955,21 +960,21 @@ Each sparse vector takes `8 * non-zero elements + 16` bytes of storage. Each ele
|
||||
|
||||
Operator | Description | Added
|
||||
--- | --- | ---
|
||||
<-> | Euclidean distance | unreleased
|
||||
<#> | negative inner product | unreleased
|
||||
<=> | cosine distance | unreleased
|
||||
<+> | taxicab distance | unreleased
|
||||
<-> | Euclidean distance | 0.7.0
|
||||
<#> | negative inner product | 0.7.0
|
||||
<=> | cosine distance | 0.7.0
|
||||
<+> | taxicab distance | 0.7.0
|
||||
|
||||
### Sparsevec Functions
|
||||
|
||||
Function | Description | Added
|
||||
--- | --- | ---
|
||||
cosine_distance(sparsevec, sparsevec) → double precision | cosine distance | unreleased
|
||||
inner_product(sparsevec, sparsevec) → double precision | inner product | unreleased
|
||||
l1_distance(sparsevec, sparsevec) → double precision | taxicab distance | unreleased
|
||||
l2_distance(sparsevec, sparsevec) → double precision | Euclidean distance | unreleased
|
||||
l2_norm(sparsevec) → double precision | Euclidean norm | unreleased
|
||||
l2_normalize(sparsevec) → sparsevec | Normalize with Euclidean norm | unreleased
|
||||
cosine_distance(sparsevec, sparsevec) → double precision | cosine distance | 0.7.0
|
||||
inner_product(sparsevec, sparsevec) → double precision | inner product | 0.7.0
|
||||
l1_distance(sparsevec, sparsevec) → double precision | taxicab distance | 0.7.0
|
||||
l2_distance(sparsevec, sparsevec) → double precision | Euclidean distance | 0.7.0
|
||||
l2_norm(sparsevec) → double precision | Euclidean norm | 0.7.0
|
||||
l2_normalize(sparsevec) → sparsevec | Normalize with Euclidean norm | 0.7.0
|
||||
|
||||
## Installation Notes - Linux and Mac
|
||||
|
||||
@@ -1046,9 +1051,9 @@ This adds pgvector to the [Postgres image](https://hub.docker.com/_/postgres) (r
|
||||
You can also build the image manually:
|
||||
|
||||
```sh
|
||||
git clone --branch v0.6.2 https://github.com/pgvector/pgvector.git
|
||||
git clone --branch v0.7.2 https://github.com/pgvector/pgvector.git
|
||||
cd pgvector
|
||||
docker build --build-arg PG_MAJOR=16 -t myuser/pgvector .
|
||||
docker build --pull --build-arg PG_MAJOR=16 -t myuser/pgvector .
|
||||
```
|
||||
|
||||
### Homebrew
|
||||
|
||||
2
sql/vector--0.7.0--0.7.1.sql
Normal file
2
sql/vector--0.7.0--0.7.1.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.7.1'" to load this file. \quit
|
||||
2
sql/vector--0.7.1--0.7.2.sql
Normal file
2
sql/vector--0.7.1--0.7.2.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.7.2'" to load this file. \quit
|
||||
@@ -11,7 +11,7 @@
|
||||
#ifdef BIT_DISPATCH
|
||||
#include <immintrin.h>
|
||||
|
||||
#if defined(HAVE__GET_CPUID)
|
||||
#if defined(USE__GET_CPUID)
|
||||
#include <cpuid.h>
|
||||
#else
|
||||
#include <intrin.h>
|
||||
@@ -173,7 +173,7 @@ SupportsAvx512Popcount()
|
||||
{
|
||||
unsigned int exx[4] = {0, 0, 0, 0};
|
||||
|
||||
#if defined(HAVE__GET_CPUID)
|
||||
#if defined(USE__GET_CPUID)
|
||||
__get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
|
||||
#else
|
||||
__cpuid(exx, 1);
|
||||
@@ -187,7 +187,7 @@ SupportsAvx512Popcount()
|
||||
if ((_xgetbv(0) & 0xe6) != 0xe6)
|
||||
return false;
|
||||
|
||||
#if defined(HAVE__GET_CPUID)
|
||||
#if defined(USE__GET_CPUID)
|
||||
__get_cpuid_count(7, 0, &exx[0], &exx[1], &exx[2], &exx[3]);
|
||||
#else
|
||||
__cpuidex(exx, 7, 0);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#ifdef HALFVEC_DISPATCH
|
||||
#include <immintrin.h>
|
||||
|
||||
#if defined(HAVE__GET_CPUID)
|
||||
#if defined(USE__GET_CPUID)
|
||||
#include <cpuid.h>
|
||||
#else
|
||||
#include <intrin.h>
|
||||
@@ -254,7 +254,7 @@ SupportsCpuFeature(unsigned int feature)
|
||||
{
|
||||
unsigned int exx[4] = {0, 0, 0, 0};
|
||||
|
||||
#if defined(HAVE__GET_CPUID)
|
||||
#if defined(USE__GET_CPUID)
|
||||
__get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
|
||||
#else
|
||||
__cpuid(exx, 1);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/* TODO Move to better place */
|
||||
#ifndef DISABLE_DISPATCH
|
||||
/* Only enable for more recent compilers to keep build process simple */
|
||||
#if defined(__x86_64__) && defined(__GNUC__) && __GNUC__ >= 8
|
||||
#if defined(__x86_64__) && defined(__GNUC__) && __GNUC__ >= 9
|
||||
#define USE_DISPATCH
|
||||
#elif defined(__x86_64__) && defined(__clang_major__) && __clang_major__ >= 7
|
||||
#define USE_DISPATCH
|
||||
@@ -19,9 +19,17 @@
|
||||
#endif
|
||||
|
||||
/* target_clones requires glibc */
|
||||
#if defined(USE_DISPATCH) && defined(__gnu_linux__)
|
||||
#if defined(USE_DISPATCH) && defined(__gnu_linux__) && defined(__has_attribute)
|
||||
/* Use separate line for portability */
|
||||
#if __has_attribute(target_clones)
|
||||
#define USE_TARGET_CLONES
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Apple clang check needed for universal binaries on Mac */
|
||||
#if defined(USE_DISPATCH) && (defined(HAVE__GET_CPUID) || defined(__apple_build_version__))
|
||||
#define USE__GET_CPUID
|
||||
#endif
|
||||
|
||||
#if defined(USE_DISPATCH)
|
||||
#define HALFVEC_DISPATCH
|
||||
|
||||
@@ -393,7 +393,7 @@ void HnswInitNeighbors(char *base, HnswElement element, int m, HnswAllocator *
|
||||
bool HnswInsertTupleOnDisk(Relation index, Datum value, Datum *values, bool *isnull, ItemPointer heap_tid, bool building);
|
||||
void HnswUpdateNeighborsOnDisk(Relation index, FmgrInfo *procinfo, Oid collation, HnswElement e, int m, bool checkExisting, bool building);
|
||||
void HnswLoadElementFromTuple(HnswElement element, HnswElementTuple etup, bool loadHeaptids, bool loadVec);
|
||||
void HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, Oid collation, bool loadVec);
|
||||
void HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, Oid collation, bool loadVec, float *maxDistance);
|
||||
void HnswSetElementTuple(char *base, HnswElementTuple etup, HnswElement element);
|
||||
void HnswUpdateConnection(char *base, HnswElement element, HnswCandidate * hc, int lm, int lc, int *updateIdx, Relation index, FmgrInfo *procinfo, Oid collation);
|
||||
void HnswLoadNeighbors(HnswElement element, Relation index, int m);
|
||||
|
||||
@@ -1121,8 +1121,8 @@ BuildIndex(Relation heap, Relation index, IndexInfo *indexInfo,
|
||||
|
||||
BuildGraph(buildstate, forkNum);
|
||||
|
||||
if (RelationNeedsWAL(index))
|
||||
log_newpage_range(index, forkNum, 0, RelationGetNumberOfBlocks(index), true);
|
||||
if (RelationNeedsWAL(index) || forkNum == INIT_FORKNUM)
|
||||
log_newpage_range(index, forkNum, 0, RelationGetNumberOfBlocksInFork(index, forkNum), true);
|
||||
|
||||
FreeBuildState(buildstate);
|
||||
}
|
||||
|
||||
@@ -300,6 +300,9 @@ HnswGetMetaPageInfo(Relation index, int *m, HnswElement * entryPoint)
|
||||
page = BufferGetPage(buf);
|
||||
metap = HnswPageGetMeta(page);
|
||||
|
||||
if (unlikely(metap->magicNumber != HNSW_MAGIC_NUMBER))
|
||||
elog(ERROR, "hnsw index is not valid");
|
||||
|
||||
if (m != NULL)
|
||||
*m = metap->m;
|
||||
|
||||
@@ -545,7 +548,7 @@ HnswLoadElementFromTuple(HnswElement element, HnswElementTuple etup, bool loadHe
|
||||
* Load an element and optionally get its distance from q
|
||||
*/
|
||||
void
|
||||
HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, Oid collation, bool loadVec)
|
||||
HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, Oid collation, bool loadVec, float *maxDistance)
|
||||
{
|
||||
Buffer buf;
|
||||
Page page;
|
||||
@@ -560,9 +563,6 @@ HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index,
|
||||
|
||||
Assert(HnswIsElementTuple(etup));
|
||||
|
||||
/* Load element */
|
||||
HnswLoadElementFromTuple(element, etup, true, loadVec);
|
||||
|
||||
/* Calculate distance */
|
||||
if (distance != NULL)
|
||||
{
|
||||
@@ -572,6 +572,10 @@ HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index,
|
||||
*distance = (float) DatumGetFloat8(FunctionCall2Coll(procinfo, collation, *q, PointerGetDatum(&etup->data)));
|
||||
}
|
||||
|
||||
/* Load element */
|
||||
if (distance == NULL || maxDistance == NULL || *distance < *maxDistance)
|
||||
HnswLoadElementFromTuple(element, etup, true, loadVec);
|
||||
|
||||
UnlockReleaseBuffer(buf);
|
||||
}
|
||||
|
||||
@@ -599,7 +603,7 @@ HnswEntryCandidate(char *base, HnswElement entryPoint, Datum q, Relation index,
|
||||
if (index == NULL)
|
||||
hc->distance = GetCandidateDistance(base, hc, q, procinfo, collation);
|
||||
else
|
||||
HnswLoadElement(entryPoint, &hc->distance, &q, index, procinfo, collation, loadVec);
|
||||
HnswLoadElement(entryPoint, &hc->distance, &q, index, procinfo, collation, loadVec, NULL);
|
||||
return hc;
|
||||
}
|
||||
|
||||
@@ -795,25 +799,27 @@ HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, F
|
||||
{
|
||||
float eDistance;
|
||||
HnswElement eElement = HnswPtrAccess(base, e->element);
|
||||
bool alwaysAdd = wlen < ef;
|
||||
|
||||
f = ((HnswPairingHeapNode *) pairingheap_first(W))->inner;
|
||||
|
||||
if (index == NULL)
|
||||
eDistance = GetCandidateDistance(base, e, q, procinfo, collation);
|
||||
else
|
||||
HnswLoadElement(eElement, &eDistance, &q, index, procinfo, collation, inserting);
|
||||
HnswLoadElement(eElement, &eDistance, &q, index, procinfo, collation, inserting, alwaysAdd ? NULL : &f->distance);
|
||||
|
||||
Assert(!eElement->deleted);
|
||||
|
||||
/* Make robust to issues */
|
||||
if (eElement->level < lc)
|
||||
continue;
|
||||
|
||||
if (eDistance < f->distance || wlen < ef)
|
||||
if (eDistance < f->distance || alwaysAdd)
|
||||
{
|
||||
/* Copy e */
|
||||
HnswCandidate *ec = palloc(sizeof(HnswCandidate));
|
||||
HnswCandidate *ec;
|
||||
|
||||
Assert(!eElement->deleted);
|
||||
|
||||
/* Make robust to issues */
|
||||
if (eElement->level < lc)
|
||||
continue;
|
||||
|
||||
/* Copy e */
|
||||
ec = palloc(sizeof(HnswCandidate));
|
||||
HnswPtrStore(base, ec->element, eElement);
|
||||
ec->distance = eDistance;
|
||||
|
||||
@@ -1102,7 +1108,7 @@ HnswUpdateConnection(char *base, HnswElement element, HnswCandidate * hc, int lm
|
||||
HnswElement hc3Element = HnswPtrAccess(base, hc3->element);
|
||||
|
||||
if (HnswPtrIsNull(base, hc3Element->value))
|
||||
HnswLoadElement(hc3Element, &hc3->distance, &q, index, procinfo, collation, true);
|
||||
HnswLoadElement(hc3Element, &hc3->distance, &q, index, procinfo, collation, true, NULL);
|
||||
else
|
||||
hc3->distance = GetCandidateDistance(base, hc3, q, procinfo, collation);
|
||||
|
||||
|
||||
@@ -256,7 +256,7 @@ RepairGraphEntryPoint(HnswVacuumState * vacuumstate)
|
||||
LockPage(index, HNSW_UPDATE_LOCK, ShareLock);
|
||||
|
||||
/* Load element */
|
||||
HnswLoadElement(highestPoint, NULL, NULL, index, vacuumstate->procinfo, vacuumstate->collation, true);
|
||||
HnswLoadElement(highestPoint, NULL, NULL, index, vacuumstate->procinfo, vacuumstate->collation, true, NULL);
|
||||
|
||||
/* Repair if needed */
|
||||
if (NeedsUpdated(vacuumstate, highestPoint))
|
||||
@@ -294,7 +294,7 @@ RepairGraphEntryPoint(HnswVacuumState * vacuumstate)
|
||||
* is outdated, this can remove connections at higher levels in
|
||||
* the graph until they are repaired, but this should be fine.
|
||||
*/
|
||||
HnswLoadElement(entryPoint, NULL, NULL, index, vacuumstate->procinfo, vacuumstate->collation, true);
|
||||
HnswLoadElement(entryPoint, NULL, NULL, index, vacuumstate->procinfo, vacuumstate->collation, true, NULL);
|
||||
|
||||
if (NeedsUpdated(vacuumstate, entryPoint))
|
||||
{
|
||||
|
||||
@@ -1006,6 +1006,10 @@ BuildIndex(Relation heap, Relation index, IndexInfo *indexInfo,
|
||||
CreateListPages(index, buildstate->centers, buildstate->dimensions, buildstate->lists, forkNum, &buildstate->listInfo);
|
||||
CreateEntryPages(buildstate, forkNum);
|
||||
|
||||
/* Write WAL for initialization fork since GenericXLog functions do not */
|
||||
if (forkNum == INIT_FORKNUM)
|
||||
log_newpage_range(index, forkNum, 0, RelationGetNumberOfBlocksInFork(index, forkNum), true);
|
||||
|
||||
FreeBuildState(buildstate);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,9 @@ InsertTuple(Relation index, Datum *values, bool *isnull, ItemPointer heap_tid, R
|
||||
value = IvfflatNormValue(typeInfo, collation, value);
|
||||
}
|
||||
|
||||
/* Ensure index is valid */
|
||||
IvfflatGetMetaPageInfo(index, NULL, NULL);
|
||||
|
||||
/* Find the insert page - sets the page and list info */
|
||||
FindInsertPage(index, values, &insertPage, &listInfo);
|
||||
Assert(BlockNumberIsValid(insertPage));
|
||||
|
||||
@@ -170,7 +170,11 @@ IvfflatGetMetaPageInfo(Relation index, int *lists, int *dimensions)
|
||||
page = BufferGetPage(buf);
|
||||
metap = IvfflatPageGetMeta(page);
|
||||
|
||||
*lists = metap->lists;
|
||||
if (unlikely(metap->magicNumber != IVFFLAT_MAGIC_NUMBER))
|
||||
elog(ERROR, "ivfflat index is not valid");
|
||||
|
||||
if (lists != NULL)
|
||||
*lists = metap->lists;
|
||||
|
||||
if (dimensions != NULL)
|
||||
*dimensions = metap->dimensions;
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "CREATE EXTENSION vector" to load this file. \quit
|
||||
Use "CREATE EXTENSION vector" to load this file.
|
||||
672
test/expected/vector_type.out
Normal file
672
test/expected/vector_type.out
Normal file
@@ -0,0 +1,672 @@
|
||||
SELECT '[1,2,3]'::vector;
|
||||
vector
|
||||
---------
|
||||
[1,2,3]
|
||||
(1 row)
|
||||
|
||||
SELECT '[-1,-2,-3]'::vector;
|
||||
vector
|
||||
------------
|
||||
[-1,-2,-3]
|
||||
(1 row)
|
||||
|
||||
SELECT '[1.,2.,3.]'::vector;
|
||||
vector
|
||||
---------
|
||||
[1,2,3]
|
||||
(1 row)
|
||||
|
||||
SELECT ' [ 1, 2 , 3 ] '::vector;
|
||||
vector
|
||||
---------
|
||||
[1,2,3]
|
||||
(1 row)
|
||||
|
||||
SELECT '[1.23456]'::vector;
|
||||
vector
|
||||
-----------
|
||||
[1.23456]
|
||||
(1 row)
|
||||
|
||||
SELECT '[hello,1]'::vector;
|
||||
ERROR: invalid input syntax for type vector: "[hello,1]"
|
||||
LINE 1: SELECT '[hello,1]'::vector;
|
||||
^
|
||||
SELECT '[NaN,1]'::vector;
|
||||
ERROR: NaN not allowed in vector
|
||||
LINE 1: SELECT '[NaN,1]'::vector;
|
||||
^
|
||||
SELECT '[Infinity,1]'::vector;
|
||||
ERROR: infinite value not allowed in vector
|
||||
LINE 1: SELECT '[Infinity,1]'::vector;
|
||||
^
|
||||
SELECT '[-Infinity,1]'::vector;
|
||||
ERROR: infinite value not allowed in vector
|
||||
LINE 1: SELECT '[-Infinity,1]'::vector;
|
||||
^
|
||||
SELECT '[1.5e38,-1.5e38]'::vector;
|
||||
vector
|
||||
--------------------
|
||||
[1.5e+38,-1.5e+38]
|
||||
(1 row)
|
||||
|
||||
SELECT '[1.5e+38,-1.5e+38]'::vector;
|
||||
vector
|
||||
--------------------
|
||||
[1.5e+38,-1.5e+38]
|
||||
(1 row)
|
||||
|
||||
SELECT '[1.5e-38,-1.5e-38]'::vector;
|
||||
vector
|
||||
--------------------
|
||||
[1.5e-38,-1.5e-38]
|
||||
(1 row)
|
||||
|
||||
SELECT '[4e38,1]'::vector;
|
||||
ERROR: "4e38" is out of range for type vector
|
||||
LINE 1: SELECT '[4e38,1]'::vector;
|
||||
^
|
||||
SELECT '[-4e38,1]'::vector;
|
||||
ERROR: "-4e38" is out of range for type vector
|
||||
LINE 1: SELECT '[-4e38,1]'::vector;
|
||||
^
|
||||
SELECT '[1e-46,1]'::vector;
|
||||
vector
|
||||
--------
|
||||
[0,1]
|
||||
(1 row)
|
||||
|
||||
SELECT '[-1e-46,1]'::vector;
|
||||
vector
|
||||
--------
|
||||
[-0,1]
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2,3'::vector;
|
||||
ERROR: invalid input syntax for type vector: "[1,2,3"
|
||||
LINE 1: SELECT '[1,2,3'::vector;
|
||||
^
|
||||
SELECT '[1,2,3]9'::vector;
|
||||
ERROR: invalid input syntax for type vector: "[1,2,3]9"
|
||||
LINE 1: SELECT '[1,2,3]9'::vector;
|
||||
^
|
||||
DETAIL: Junk after closing right brace.
|
||||
SELECT '1,2,3'::vector;
|
||||
ERROR: invalid input syntax for type vector: "1,2,3"
|
||||
LINE 1: SELECT '1,2,3'::vector;
|
||||
^
|
||||
DETAIL: Vector contents must start with "[".
|
||||
SELECT ''::vector;
|
||||
ERROR: invalid input syntax for type vector: ""
|
||||
LINE 1: SELECT ''::vector;
|
||||
^
|
||||
DETAIL: Vector contents must start with "[".
|
||||
SELECT '['::vector;
|
||||
ERROR: invalid input syntax for type vector: "["
|
||||
LINE 1: SELECT '['::vector;
|
||||
^
|
||||
SELECT '[ '::vector;
|
||||
ERROR: invalid input syntax for type vector: "[ "
|
||||
LINE 1: SELECT '[ '::vector;
|
||||
^
|
||||
SELECT '[,'::vector;
|
||||
ERROR: invalid input syntax for type vector: "[,"
|
||||
LINE 1: SELECT '[,'::vector;
|
||||
^
|
||||
SELECT '[]'::vector;
|
||||
ERROR: vector must have at least 1 dimension
|
||||
LINE 1: SELECT '[]'::vector;
|
||||
^
|
||||
SELECT '[ ]'::vector;
|
||||
ERROR: vector must have at least 1 dimension
|
||||
LINE 1: SELECT '[ ]'::vector;
|
||||
^
|
||||
SELECT '[,]'::vector;
|
||||
ERROR: invalid input syntax for type vector: "[,]"
|
||||
LINE 1: SELECT '[,]'::vector;
|
||||
^
|
||||
SELECT '[1,]'::vector;
|
||||
ERROR: invalid input syntax for type vector: "[1,]"
|
||||
LINE 1: SELECT '[1,]'::vector;
|
||||
^
|
||||
SELECT '[1a]'::vector;
|
||||
ERROR: invalid input syntax for type vector: "[1a]"
|
||||
LINE 1: SELECT '[1a]'::vector;
|
||||
^
|
||||
SELECT '[1,,3]'::vector;
|
||||
ERROR: invalid input syntax for type vector: "[1,,3]"
|
||||
LINE 1: SELECT '[1,,3]'::vector;
|
||||
^
|
||||
SELECT '[1, ,3]'::vector;
|
||||
ERROR: invalid input syntax for type vector: "[1, ,3]"
|
||||
LINE 1: SELECT '[1, ,3]'::vector;
|
||||
^
|
||||
SELECT '[1,2,3]'::vector(3);
|
||||
vector
|
||||
---------
|
||||
[1,2,3]
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2,3]'::vector(2);
|
||||
ERROR: expected 2 dimensions, not 3
|
||||
SELECT '[1,2,3]'::vector(3, 2);
|
||||
ERROR: invalid type modifier
|
||||
LINE 1: SELECT '[1,2,3]'::vector(3, 2);
|
||||
^
|
||||
SELECT '[1,2,3]'::vector('a');
|
||||
ERROR: invalid input syntax for type integer: "a"
|
||||
LINE 1: SELECT '[1,2,3]'::vector('a');
|
||||
^
|
||||
SELECT '[1,2,3]'::vector(0);
|
||||
ERROR: dimensions for type vector must be at least 1
|
||||
LINE 1: SELECT '[1,2,3]'::vector(0);
|
||||
^
|
||||
SELECT '[1,2,3]'::vector(16001);
|
||||
ERROR: dimensions for type vector cannot exceed 16000
|
||||
LINE 1: SELECT '[1,2,3]'::vector(16001);
|
||||
^
|
||||
SELECT unnest('{"[1,2,3]", "[4,5,6]"}'::vector[]);
|
||||
unnest
|
||||
---------
|
||||
[1,2,3]
|
||||
[4,5,6]
|
||||
(2 rows)
|
||||
|
||||
SELECT '{"[1,2,3]"}'::vector(2)[];
|
||||
ERROR: expected 2 dimensions, not 3
|
||||
SELECT '[1,2,3]'::vector + '[4,5,6]';
|
||||
?column?
|
||||
----------
|
||||
[5,7,9]
|
||||
(1 row)
|
||||
|
||||
SELECT '[3e38]'::vector + '[3e38]';
|
||||
ERROR: value out of range: overflow
|
||||
SELECT '[1,2]'::vector + '[3]';
|
||||
ERROR: different vector dimensions 2 and 1
|
||||
SELECT '[1,2,3]'::vector - '[4,5,6]';
|
||||
?column?
|
||||
------------
|
||||
[-3,-3,-3]
|
||||
(1 row)
|
||||
|
||||
SELECT '[-3e38]'::vector - '[3e38]';
|
||||
ERROR: value out of range: overflow
|
||||
SELECT '[1,2]'::vector - '[3]';
|
||||
ERROR: different vector dimensions 2 and 1
|
||||
SELECT '[1,2,3]'::vector * '[4,5,6]';
|
||||
?column?
|
||||
-----------
|
||||
[4,10,18]
|
||||
(1 row)
|
||||
|
||||
SELECT '[1e37]'::vector * '[1e37]';
|
||||
ERROR: value out of range: overflow
|
||||
SELECT '[1e-37]'::vector * '[1e-37]';
|
||||
ERROR: value out of range: underflow
|
||||
SELECT '[1,2]'::vector * '[3]';
|
||||
ERROR: different vector dimensions 2 and 1
|
||||
SELECT '[1,2,3]'::vector || '[4,5]';
|
||||
?column?
|
||||
-------------
|
||||
[1,2,3,4,5]
|
||||
(1 row)
|
||||
|
||||
SELECT array_fill(0, ARRAY[16000])::vector || '[1]';
|
||||
ERROR: vector cannot have more than 16000 dimensions
|
||||
SELECT '[1,2,3]'::vector < '[1,2,3]';
|
||||
?column?
|
||||
----------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2,3]'::vector < '[1,2]';
|
||||
?column?
|
||||
----------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2,3]'::vector <= '[1,2,3]';
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2,3]'::vector <= '[1,2]';
|
||||
?column?
|
||||
----------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2,3]'::vector = '[1,2,3]';
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2,3]'::vector = '[1,2]';
|
||||
?column?
|
||||
----------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2,3]'::vector != '[1,2,3]';
|
||||
?column?
|
||||
----------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2,3]'::vector != '[1,2]';
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2,3]'::vector >= '[1,2,3]';
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2,3]'::vector >= '[1,2]';
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2,3]'::vector > '[1,2,3]';
|
||||
?column?
|
||||
----------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2,3]'::vector > '[1,2]';
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT vector_cmp('[1,2,3]', '[1,2,3]');
|
||||
vector_cmp
|
||||
------------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
SELECT vector_cmp('[1,2,3]', '[0,0,0]');
|
||||
vector_cmp
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT vector_cmp('[0,0,0]', '[1,2,3]');
|
||||
vector_cmp
|
||||
------------
|
||||
-1
|
||||
(1 row)
|
||||
|
||||
SELECT vector_cmp('[1,2]', '[1,2,3]');
|
||||
vector_cmp
|
||||
------------
|
||||
-1
|
||||
(1 row)
|
||||
|
||||
SELECT vector_cmp('[1,2,3]', '[1,2]');
|
||||
vector_cmp
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT vector_cmp('[1,2]', '[2,3,4]');
|
||||
vector_cmp
|
||||
------------
|
||||
-1
|
||||
(1 row)
|
||||
|
||||
SELECT vector_cmp('[2,3]', '[1,2,3]');
|
||||
vector_cmp
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT vector_dims('[1,2,3]'::vector);
|
||||
vector_dims
|
||||
-------------
|
||||
3
|
||||
(1 row)
|
||||
|
||||
SELECT round(vector_norm('[1,1]')::numeric, 5);
|
||||
round
|
||||
---------
|
||||
1.41421
|
||||
(1 row)
|
||||
|
||||
SELECT vector_norm('[3,4]');
|
||||
vector_norm
|
||||
-------------
|
||||
5
|
||||
(1 row)
|
||||
|
||||
SELECT vector_norm('[0,1]');
|
||||
vector_norm
|
||||
-------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT vector_norm('[3e37,4e37]')::real;
|
||||
vector_norm
|
||||
-------------
|
||||
5e+37
|
||||
(1 row)
|
||||
|
||||
SELECT vector_norm('[0,0]');
|
||||
vector_norm
|
||||
-------------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
SELECT vector_norm('[2]');
|
||||
vector_norm
|
||||
-------------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
SELECT l2_distance('[0,0]'::vector, '[3,4]');
|
||||
l2_distance
|
||||
-------------
|
||||
5
|
||||
(1 row)
|
||||
|
||||
SELECT l2_distance('[0,0]'::vector, '[0,1]');
|
||||
l2_distance
|
||||
-------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT l2_distance('[1,2]'::vector, '[3]');
|
||||
ERROR: different vector dimensions 2 and 1
|
||||
SELECT l2_distance('[3e38]'::vector, '[-3e38]');
|
||||
l2_distance
|
||||
-------------
|
||||
Infinity
|
||||
(1 row)
|
||||
|
||||
SELECT l2_distance('[1,1,1,1,1,1,1,1,1]'::vector, '[1,1,1,1,1,1,1,4,5]');
|
||||
l2_distance
|
||||
-------------
|
||||
5
|
||||
(1 row)
|
||||
|
||||
SELECT '[0,0]'::vector <-> '[3,4]';
|
||||
?column?
|
||||
----------
|
||||
5
|
||||
(1 row)
|
||||
|
||||
SELECT inner_product('[1,2]'::vector, '[3,4]');
|
||||
inner_product
|
||||
---------------
|
||||
11
|
||||
(1 row)
|
||||
|
||||
SELECT inner_product('[1,2]'::vector, '[3]');
|
||||
ERROR: different vector dimensions 2 and 1
|
||||
SELECT inner_product('[3e38]'::vector, '[3e38]');
|
||||
inner_product
|
||||
---------------
|
||||
Infinity
|
||||
(1 row)
|
||||
|
||||
SELECT inner_product('[1,1,1,1,1,1,1,1,1]'::vector, '[1,2,3,4,5,6,7,8,9]');
|
||||
inner_product
|
||||
---------------
|
||||
45
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2]'::vector <#> '[3,4]';
|
||||
?column?
|
||||
----------
|
||||
-11
|
||||
(1 row)
|
||||
|
||||
SELECT cosine_distance('[1,2]'::vector, '[2,4]');
|
||||
cosine_distance
|
||||
-----------------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
SELECT cosine_distance('[1,2]'::vector, '[0,0]');
|
||||
cosine_distance
|
||||
-----------------
|
||||
NaN
|
||||
(1 row)
|
||||
|
||||
SELECT cosine_distance('[1,1]'::vector, '[1,1]');
|
||||
cosine_distance
|
||||
-----------------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
SELECT cosine_distance('[1,0]'::vector, '[0,2]');
|
||||
cosine_distance
|
||||
-----------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT cosine_distance('[1,1]'::vector, '[-1,-1]');
|
||||
cosine_distance
|
||||
-----------------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
SELECT cosine_distance('[1,2]'::vector, '[3]');
|
||||
ERROR: different vector dimensions 2 and 1
|
||||
SELECT cosine_distance('[1,1]'::vector, '[1.1,1.1]');
|
||||
cosine_distance
|
||||
-----------------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
SELECT cosine_distance('[1,1]'::vector, '[-1.1,-1.1]');
|
||||
cosine_distance
|
||||
-----------------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
SELECT cosine_distance('[3e38]'::vector, '[3e38]');
|
||||
cosine_distance
|
||||
-----------------
|
||||
NaN
|
||||
(1 row)
|
||||
|
||||
SELECT cosine_distance('[1,2,3,4,5,6,7,8,9]'::vector, '[1,2,3,4,5,6,7,8,9]');
|
||||
cosine_distance
|
||||
-----------------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
SELECT cosine_distance('[1,2,3,4,5,6,7,8,9]'::vector, '[-1,-2,-3,-4,-5,-6,-7,-8,-9]');
|
||||
cosine_distance
|
||||
-----------------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
SELECT '[1,2]'::vector <=> '[2,4]';
|
||||
?column?
|
||||
----------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
SELECT l1_distance('[0,0]'::vector, '[3,4]');
|
||||
l1_distance
|
||||
-------------
|
||||
7
|
||||
(1 row)
|
||||
|
||||
SELECT l1_distance('[0,0]'::vector, '[0,1]');
|
||||
l1_distance
|
||||
-------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT l1_distance('[1,2]'::vector, '[3]');
|
||||
ERROR: different vector dimensions 2 and 1
|
||||
SELECT l1_distance('[3e38]'::vector, '[-3e38]');
|
||||
l1_distance
|
||||
-------------
|
||||
Infinity
|
||||
(1 row)
|
||||
|
||||
SELECT l1_distance('[1,2,3,4,5,6,7,8,9]'::vector, '[1,2,3,4,5,6,7,8,9]');
|
||||
l1_distance
|
||||
-------------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
SELECT l1_distance('[1,2,3,4,5,6,7,8,9]'::vector, '[0,3,2,5,4,7,6,9,8]');
|
||||
l1_distance
|
||||
-------------
|
||||
9
|
||||
(1 row)
|
||||
|
||||
SELECT '[0,0]'::vector <+> '[3,4]';
|
||||
?column?
|
||||
----------
|
||||
7
|
||||
(1 row)
|
||||
|
||||
SELECT l2_normalize('[3,4]'::vector);
|
||||
l2_normalize
|
||||
--------------
|
||||
[0.6,0.8]
|
||||
(1 row)
|
||||
|
||||
SELECT l2_normalize('[3,0]'::vector);
|
||||
l2_normalize
|
||||
--------------
|
||||
[1,0]
|
||||
(1 row)
|
||||
|
||||
SELECT l2_normalize('[0,0.1]'::vector);
|
||||
l2_normalize
|
||||
--------------
|
||||
[0,1]
|
||||
(1 row)
|
||||
|
||||
SELECT l2_normalize('[0,0]'::vector);
|
||||
l2_normalize
|
||||
--------------
|
||||
[0,0]
|
||||
(1 row)
|
||||
|
||||
SELECT l2_normalize('[3e38]'::vector);
|
||||
l2_normalize
|
||||
--------------
|
||||
[1]
|
||||
(1 row)
|
||||
|
||||
SELECT binary_quantize('[1,0,-1]'::vector);
|
||||
binary_quantize
|
||||
-----------------
|
||||
100
|
||||
(1 row)
|
||||
|
||||
SELECT binary_quantize('[0,0.1,-0.2,-0.3,0.4,0.5,0.6,-0.7,0.8,-0.9,1]'::vector);
|
||||
binary_quantize
|
||||
-----------------
|
||||
01001110101
|
||||
(1 row)
|
||||
|
||||
SELECT subvector('[1,2,3,4,5]'::vector, 1, 3);
|
||||
subvector
|
||||
-----------
|
||||
[1,2,3]
|
||||
(1 row)
|
||||
|
||||
SELECT subvector('[1,2,3,4,5]'::vector, 3, 2);
|
||||
subvector
|
||||
-----------
|
||||
[3,4]
|
||||
(1 row)
|
||||
|
||||
SELECT subvector('[1,2,3,4,5]'::vector, -1, 3);
|
||||
subvector
|
||||
-----------
|
||||
[1]
|
||||
(1 row)
|
||||
|
||||
SELECT subvector('[1,2,3,4,5]'::vector, 3, 9);
|
||||
subvector
|
||||
-----------
|
||||
[3,4,5]
|
||||
(1 row)
|
||||
|
||||
SELECT subvector('[1,2,3,4,5]'::vector, 1, 0);
|
||||
ERROR: vector must have at least 1 dimension
|
||||
SELECT subvector('[1,2,3,4,5]'::vector, 3, -1);
|
||||
ERROR: vector must have at least 1 dimension
|
||||
SELECT subvector('[1,2,3,4,5]'::vector, -1, 2);
|
||||
ERROR: vector must have at least 1 dimension
|
||||
SELECT subvector('[1,2,3,4,5]'::vector, 2147483647, 10);
|
||||
ERROR: vector must have at least 1 dimension
|
||||
SELECT subvector('[1,2,3,4,5]'::vector, 3, 2147483647);
|
||||
subvector
|
||||
-----------
|
||||
[3,4,5]
|
||||
(1 row)
|
||||
|
||||
SELECT subvector('[1,2,3,4,5]'::vector, -2147483644, 2147483647);
|
||||
subvector
|
||||
-----------
|
||||
[1,2]
|
||||
(1 row)
|
||||
|
||||
SELECT avg(v) FROM unnest(ARRAY['[1,2,3]'::vector, '[3,5,7]']) v;
|
||||
avg
|
||||
-----------
|
||||
[2,3.5,5]
|
||||
(1 row)
|
||||
|
||||
SELECT avg(v) FROM unnest(ARRAY['[1,2,3]'::vector, '[3,5,7]', NULL]) v;
|
||||
avg
|
||||
-----------
|
||||
[2,3.5,5]
|
||||
(1 row)
|
||||
|
||||
SELECT avg(v) FROM unnest(ARRAY[]::vector[]) v;
|
||||
avg
|
||||
-----
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT avg(v) FROM unnest(ARRAY['[1,2]'::vector, '[3]']) v;
|
||||
ERROR: expected 2 dimensions, not 1
|
||||
SELECT avg(v) FROM unnest(ARRAY['[3e38]'::vector, '[3e38]']) v;
|
||||
avg
|
||||
---------
|
||||
[3e+38]
|
||||
(1 row)
|
||||
|
||||
SELECT vector_avg(array_agg(n)) FROM generate_series(1, 16002) n;
|
||||
ERROR: vector cannot have more than 16000 dimensions
|
||||
SELECT sum(v) FROM unnest(ARRAY['[1,2,3]'::vector, '[3,5,7]']) v;
|
||||
sum
|
||||
----------
|
||||
[4,7,10]
|
||||
(1 row)
|
||||
|
||||
SELECT sum(v) FROM unnest(ARRAY['[1,2,3]'::vector, '[3,5,7]', NULL]) v;
|
||||
sum
|
||||
----------
|
||||
[4,7,10]
|
||||
(1 row)
|
||||
|
||||
SELECT sum(v) FROM unnest(ARRAY[]::vector[]) v;
|
||||
sum
|
||||
-----
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT sum(v) FROM unnest(ARRAY['[1,2]'::vector, '[3]']) v;
|
||||
ERROR: different vector dimensions 2 and 1
|
||||
SELECT sum(v) FROM unnest(ARRAY['[3e38]'::vector, '[3e38]']) v;
|
||||
ERROR: value out of range: overflow
|
||||
@@ -91,7 +91,7 @@ for my $i (0 .. $#operators)
|
||||
));
|
||||
|
||||
# Test approximate results
|
||||
my $min = $operator eq "<#>" ? 0.98 : 0.99;
|
||||
my $min = $operator eq "<#>" ? 0.97 : 0.99;
|
||||
test_recall($min, $operator);
|
||||
|
||||
$node->safe_psql("postgres", "DROP INDEX idx;");
|
||||
|
||||
@@ -100,7 +100,7 @@ for my $i (0 .. $#operators)
|
||||
}
|
||||
|
||||
# Test approximate results
|
||||
my $min = $operator eq "<#>" ? 0.98 : 0.99;
|
||||
my $min = $operator eq "<#>" ? 0.97 : 0.99;
|
||||
test_recall($min, $operator);
|
||||
|
||||
$node->safe_psql("postgres", "DROP INDEX idx;");
|
||||
|
||||
@@ -91,7 +91,7 @@ for my $i (0 .. $#operators)
|
||||
));
|
||||
|
||||
# Test approximate results
|
||||
my $min = $operator eq "<#>" ? 0.98 : 0.99;
|
||||
my $min = $operator eq "<#>" ? 0.97 : 0.99;
|
||||
test_recall($min, $operator);
|
||||
|
||||
$node->safe_psql("postgres", "DROP INDEX idx;");
|
||||
|
||||
@@ -100,7 +100,7 @@ for my $i (0 .. $#operators)
|
||||
}
|
||||
|
||||
# Test approximate results
|
||||
my $min = $operator eq "<#>" ? 0.98 : 0.99;
|
||||
my $min = $operator eq "<#>" ? 0.97 : 0.99;
|
||||
test_recall($min, $operator);
|
||||
|
||||
$node->safe_psql("postgres", "DROP INDEX idx;");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
comment = 'vector data type and ivfflat and hnsw access methods'
|
||||
default_version = '0.6.2'
|
||||
default_version = '0.7.2'
|
||||
module_pathname = '$libdir/vector'
|
||||
relocatable = true
|
||||
|
||||
Reference in New Issue
Block a user