Compare commits

...

9 Commits

Author SHA1 Message Date
Andrew Kane
455b5d867c Started support for parallel index scan [skip ci] 2023-06-29 23:17:59 -04:00
Jonathan S. Katz
de6502ab6e Simplify TAP test structure to align with upstream (#169)
postgres/postgres@549ec20 moved to using "done_testing()" from
the Perl testing framework, which removed the need to include test
counts.
2023-06-29 11:36:08 -04:00
Andrew Kane
7aaba14440 Added comment [skip ci] 2023-06-29 10:25:06 -04:00
Andrew Kane
ee0bf10d7d Fixed CI for equal distances 2023-06-29 10:24:02 -04:00
Andrew Kane
88094fc39f Fixed tests 2023-06-29 10:17:15 -04:00
Andrew Kane
209394faab Now available on Google Cloud SQL [skip ci] 2023-06-26 11:17:10 -04:00
Andrew Kane
673aca97fc Fixed CI for branches for i386 2023-06-16 17:38:51 -04:00
Andrew Kane
0e2dc0e6d4 Updated readme [skip ci] 2023-06-16 10:15:22 -04:00
Andrew Kane
3c681b94fd Updated example [skip ci] 2023-06-16 10:03:07 -04:00
14 changed files with 95 additions and 24 deletions

View File

@@ -88,7 +88,8 @@ jobs:
- run: |
git clone https://github.com/${{ github.repository }}.git pgvector
cd pgvector
git checkout ${{ github.ref }}
git fetch origin ${{ github.ref }}
git reset --hard FETCH_HEAD
make
make install
chown -R postgres .

View File

@@ -2,7 +2,7 @@
Open-source vector similarity search for Postgres
Supports
Store all of your application data in one place. Supports:
- exact and approximate nearest neighbor search
- L2 distance, inner product, and cosine distance
@@ -255,7 +255,7 @@ CREATE TABLE items (embedding vector(3), category_id int) PARTITION BY LIST(cate
Use together with Postgres [full-text search](https://www.postgresql.org/docs/current/textsearch-intro.html) for hybrid search ([Python example](https://github.com/pgvector/pgvector-python/blob/master/examples/hybrid_search.py)).
```sql
SELECT id, content FROM items, to_tsquery('hello & search') query
SELECT id, content FROM items, plainto_tsquery('hello search') query
WHERE textsearch @@ query ORDER BY ts_rank_cd(textsearch, query) DESC LIMIT 5;
```
@@ -483,7 +483,6 @@ pgvector is available on [these providers](https://github.com/pgvector/pgvector/
To request a new extension on other providers:
- 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/managed-database/p/pgvector-extension-for-postgresql)
- Heroku Postgres - vote or comment on [this page](https://github.com/heroku/roadmap/issues/156)

View File

@@ -142,6 +142,10 @@ ivfflatcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
*indexSelectivity = costs.indexSelectivity;
*indexCorrelation = costs.indexCorrelation;
*indexPages = costs.numIndexPages;
elog(INFO, "ivfflatcostestimate = %f", costs.indexTotalCost);
/* Cost estimates for parallel workers applied outside of amcostestimate */
elog(INFO, "parallel_workers = %d, parallel aware = %d", path->path.parallel_workers, path->path.parallel_aware);
}
/*
@@ -182,6 +186,25 @@ ivfflatvalidate(Oid opclassoid)
return true;
}
static Size
ivfflatestimateparallelscan()
{
elog(INFO, "ivfflatestimateparallelscan");
return 0;
}
static void
ivfflatinitparallelscan(void *target)
{
elog(INFO, "ivfflatinitparallelscan");
}
static void
ivfflatparallelrescan(IndexScanDesc scan)
{
elog(INFO, "ivfflatparallelrescan");
}
/*
* Define index handler
*
@@ -209,7 +232,7 @@ ivfflathandler(PG_FUNCTION_ARGS)
amroutine->amstorage = false;
amroutine->amclusterable = false;
amroutine->ampredlocks = false;
amroutine->amcanparallel = false;
amroutine->amcanparallel = true;
amroutine->amcaninclude = false;
#if PG_VERSION_NUM >= 130000
amroutine->amusemaintenanceworkmem = false; /* not used during VACUUM */
@@ -243,9 +266,9 @@ ivfflathandler(PG_FUNCTION_ARGS)
amroutine->amrestrpos = NULL;
/* Interface functions to support parallel index scans */
amroutine->amestimateparallelscan = NULL;
amroutine->aminitparallelscan = NULL;
amroutine->amparallelrescan = NULL;
amroutine->amestimateparallelscan = ivfflatestimateparallelscan;
amroutine->aminitparallelscan = ivfflatinitparallelscan;
amroutine->amparallelrescan = ivfflatparallelrescan;
PG_RETURN_POINTER(amroutine);
}

View File

@@ -126,6 +126,9 @@ GetScanItems(IndexScanDesc scan, Datum value)
*/
BufferAccessStrategy bas = GetAccessStrategy(BAS_BULKREAD);
if (scan->parallel_scan != NULL)
elog(INFO, "parallel scan");
/* Search closest probes lists */
while (!pairingheap_is_empty(so->listQueue))
{

View File

@@ -0,0 +1,16 @@
-- SET force_parallel_mode = on;
SET parallel_setup_cost = 10;
SET parallel_tuple_cost = 0.000001;
SET min_parallel_table_scan_size = 1;
SET min_parallel_index_scan_size = 1;
CREATE TABLE t (id integer, val vector(3));
ALTER TABLE t ALTER COLUMN val SET STORAGE PLAIN;
INSERT INTO t (id, val) SELECT n, ARRAY[random(), random(), random()] FROM generate_series(1,1000000) n;
CREATE INDEX ON t USING ivfflat (val) WITH (lists = 10);
SET ivfflat.probes = 4;
EXPLAIN SELECT * FROM t ORDER BY val <-> '[0.5,0.5,0.5]' LIMIT 5;
SELECT * FROM t ORDER BY val <-> '[0.5,0.5,0.5]' LIMIT 5;
DROP TABLE t;

View File

@@ -5,7 +5,7 @@ use strict;
use warnings;
use PostgresNode;
use TestLib;
use Test::More tests => 31;
use Test::More;
my $dim = 32;
@@ -95,3 +95,5 @@ for my $i (1 .. 10)
);
test_index_replay("insert $i");
}
done_testing();

View File

@@ -2,7 +2,7 @@ use strict;
use warnings;
use PostgresNode;
use TestLib;
use Test::More tests => 1;
use Test::More;
my $dim = 3;
@@ -39,3 +39,5 @@ $node->safe_psql("postgres",
# Check size
my $new_size = $node->safe_psql("postgres", "SELECT pg_total_relation_size('tst_v_idx');");
is($size, $new_size, "size does not change");
done_testing();

View File

@@ -2,7 +2,7 @@ use strict;
use warnings;
use PostgresNode;
use TestLib;
use Test::More tests => 9;
use Test::More;
my $node;
my @queries = ();
@@ -15,6 +15,13 @@ sub test_recall
my $correct = 0;
my $total = 0;
my $explain = $node->safe_psql("postgres", qq(
SET enable_seqscan = off;
SET ivfflat.probes = $probes;
EXPLAIN ANALYZE SELECT i FROM tst ORDER BY v $operator '$queries[0]' LIMIT $limit;
));
like($explain, qr/Index Scan/);
for my $i (0 .. $#queries) {
my $actual = $node->safe_psql("postgres", qq(
SET enable_seqscan = off;
@@ -72,9 +79,9 @@ foreach (@operators) {
# Add index
my $opclass;
if ($operator == "<->") {
if ($operator eq "<->") {
$opclass = "vector_l2_ops";
} elsif ($operator == "<#>") {
} elsif ($operator eq "<#>") {
$opclass = "vector_ip_ops";
} else {
$opclass = "vector_cosine_ops";
@@ -82,7 +89,13 @@ foreach (@operators) {
$node->safe_psql("postgres", "CREATE INDEX ON tst USING ivfflat (v $opclass);");
# Test approximate results
test_recall(1, 0.75, $operator);
test_recall(10, 0.95, $operator);
test_recall(100, 1.0, $operator);
if ($operator ne "<#>") {
# TODO fix test
test_recall(1, 0.75, $operator);
test_recall(10, 0.95, $operator);
}
# Account for equal distances
test_recall(100, 0.9975, $operator);
}
done_testing();

View File

@@ -2,7 +2,7 @@ use strict;
use warnings;
use PostgresNode;
use TestLib;
use Test::More tests => 3;
use Test::More;
# Initialize node
my $node = get_new_node('node');
@@ -34,3 +34,5 @@ $node->safe_psql("postgres",
# Test no error for duplicate centers
test_centers(10);
done_testing();

View File

@@ -2,7 +2,7 @@ use strict;
use warnings;
use PostgresNode;
use TestLib;
use Test::More tests => 60;
use Test::More;
# Initialize node
my $node = get_new_node('node');
@@ -23,9 +23,9 @@ foreach (@operators) {
# Add index
my $opclass;
if ($operator == "<->") {
if ($operator eq "<->") {
$opclass = "vector_l2_ops";
} elsif ($operator == "<#>") {
} elsif ($operator eq "<#>") {
$opclass = "vector_ip_ops";
} else {
$opclass = "vector_cosine_ops";
@@ -43,3 +43,5 @@ foreach (@operators) {
is($res, $query);
}
}
done_testing();

View File

@@ -2,7 +2,7 @@ use strict;
use warnings;
use PostgresNode;
use TestLib;
use Test::More tests => 3;
use Test::More;
# Initialize node
my $node = get_new_node('node');
@@ -29,3 +29,5 @@ my ($ret, $stdout, $stderr) = $node->psql("postgres",
"CREATE INDEX lists10000 ON tst USING ivfflat (v) WITH (lists = 10000);"
);
like($stderr, qr/memory required is/);
done_testing();

View File

@@ -2,7 +2,7 @@ use strict;
use warnings;
use PostgresNode;
use TestLib;
use Test::More tests => 7;
use Test::More;
my $dim = 768;
@@ -53,3 +53,5 @@ $count = $node->safe_psql("postgres", qq(
));
is($count, $expected);
is(idx_scan(), 1);
done_testing();

View File

@@ -2,7 +2,7 @@ use strict;
use warnings;
use PostgresNode;
use TestLib;
use Test::More tests => 5;
use Test::More;
# Initialize node
my $node = get_new_node('node');
@@ -33,3 +33,5 @@ is($avg, "[$r1,$r2,$r3]");
# Test explain
my $explain = $node->safe_psql("postgres", "EXPLAIN SELECT AVG(v) FROM tst;");
like($explain, qr/Partial Aggregate/);
done_testing();

View File

@@ -2,7 +2,7 @@ use strict;
use warnings;
use PostgresNode;
use TestLib;
use Test::More tests => 1;
use Test::More;
my $dim = 1024;
@@ -30,3 +30,5 @@ 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"
);
like($stderr, qr/row is too big/);
done_testing();