Enable the extension
EnableCREATE EXTENSION vector;Every common task as a copy-paste SQL snippet. Each card links to the full explanation in the documentation. Filter by category or search below.
CREATE EXTENSION vector;SELECT extversion FROM pg_extension WHERE extname = 'vector';ALTER EXTENSION vector UPDATE;CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3));ALTER TABLE items ADD COLUMN embedding vector(3);INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[4,5,6]');COPY items (embedding) FROM STDIN WITH (FORMAT BINARY);INSERT INTO items (id, embedding) VALUES (1, '[1,2,3]')
ON CONFLICT (id) DO UPDATE SET embedding = EXCLUDED.embedding;UPDATE items SET embedding = '[1,2,3]' WHERE id = 1;
DELETE FROM items WHERE id = 1;SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;SELECT * FROM items WHERE id != 1
ORDER BY embedding <-> (SELECT embedding FROM items WHERE id = 1) LIMIT 5;SELECT * FROM items WHERE embedding <-> '[3,1,2]' < 5;SELECT embedding <-> '[3,1,2]' AS distance FROM items;SELECT (embedding <#> '[3,1,2]') * -1 AS inner_product FROM items;SELECT 1 - (embedding <=> '[3,1,2]') AS cosine_similarity FROM items;SELECT embedding <+> '[3,1,2]' AS l1_distance FROM items;SELECT * FROM items ORDER BY embedding <~> '101' LIMIT 5;SELECT * FROM items ORDER BY embedding <%> '101' LIMIT 5;SELECT AVG(embedding) FROM items;
SELECT category_id, AVG(embedding) FROM items GROUP BY category_id;SELECT * FROM items WHERE category_id = 123
ORDER BY embedding <-> '[3,1,2]' LIMIT 5;SELECT id, content FROM items, plainto_tsquery('hello search') query
WHERE textsearch @@ query ORDER BY ts_rank_cd(textsearch, query) DESC LIMIT 5;CREATE INDEX ON items USING hnsw (embedding vector_l2_ops);CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops);
CREATE INDEX ON items USING hnsw (embedding vector_ip_ops);CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)
WITH (m = 16, ef_construction = 64);SET hnsw.ef_search = 100;
BEGIN;
SET LOCAL hnsw.ef_search = 100;
SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;
COMMIT;CREATE INDEX ON items USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);SET ivfflat.probes = 10;SET hnsw.iterative_scan = strict_order;
SET hnsw.iterative_scan = relaxed_order;
SET ivfflat.iterative_scan = relaxed_order;
SET hnsw.max_scan_tuples = 20000;
SET hnsw.scan_mem_multiplier = 2;
SET ivfflat.max_probes = 100;CREATE INDEX ON items USING hnsw (embedding vector_l2_ops) WHERE (category_id = 123);CREATE TABLE items (embedding vector(3), category_id int) PARTITION BY LIST(category_id);WITH relaxed_results AS MATERIALIZED (
SELECT id, embedding <-> '[1,2,3]' AS distance FROM items
WHERE category_id = 123 ORDER BY distance LIMIT 5
) SELECT * FROM relaxed_results ORDER BY distance + 0; -- + 0 needed for Postgres 17+CREATE TABLE items (id bigserial PRIMARY KEY, embedding halfvec(3));
SELECT * FROM items ORDER BY embedding <-> '[1,2,3]' LIMIT 5;CREATE INDEX ON items USING hnsw ((embedding::halfvec(3)) halfvec_l2_ops);
SELECT * FROM items ORDER BY embedding::halfvec(3) <-> '[1,2,3]' LIMIT 5;CREATE TABLE items (id bigserial PRIMARY KEY, embedding bit(3));
INSERT INTO items (embedding) VALUES ('000'), ('111');CREATE INDEX ON items USING hnsw ((binary_quantize(embedding)::bit(3)) bit_hamming_ops);
SELECT * FROM (
SELECT * FROM items
ORDER BY binary_quantize(embedding)::bit(3) <~> binary_quantize('[1,-2,3]') LIMIT 20
) ORDER BY embedding <=> '[1,-2,3]' LIMIT 5;CREATE TABLE items (id bigserial PRIMARY KEY, embedding sparsevec(5));
INSERT INTO items (embedding) VALUES ('{1:1,3:2,5:3}/5'), ('{1:4,3:5,5:6}/5');
SELECT * FROM items ORDER BY embedding <-> '{1:3,3:1,5:2}/5' LIMIT 5;CREATE INDEX ON items USING hnsw ((subvector(embedding, 1, 3)::vector(3)) vector_cosine_ops);EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;SET maintenance_work_mem = '8GB';SET max_parallel_maintenance_workers = 7; -- plus leaderCREATE INDEX CONCURRENTLY ON items USING hnsw (embedding vector_l2_ops);REINDEX INDEX CONCURRENTLY index_name;
VACUUM table_name;SET max_parallel_workers_per_gather = 4;BEGIN;
SET LOCAL enable_indexscan = off; -- force exact search
SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;
COMMIT;SELECT pg_size_pretty(pg_relation_size('index_name'));