• Stars
    star
    526
  • Rank 81,351 (Top 2 %)
  • Language
    C
  • License
    Apache License 2.0
  • Created 11 months ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Hierarchical Navigable Small World (HNSW) algorithm for vector similarity search in PostgreSQL

pg_embedding

The pg_embedding extension enables the using the Hierarchical Navigable Small World (HNSW) algorithm for vector similarity search in PostgreSQL.

This extension is based on ivf-hnsw implementation of HNSW the code for the current state-of-the-art billion-scale nearest neighbor search system[1].

Using the pg_embedding extension

This section describes how to use the pg_embedding extension with a simple example demonstrating the required statements, syntax, and options.

For information about migrating from pgvector to pg_embedding, see Migrate from pgvector to pg_embedding, in the Neon documentation.

Usage summary

The statements in this usage summary are described in further detail in the following sections.

CREATE EXTENSION embedding;
CREATE TABLE documents(id integer PRIMARY KEY, embedding real[]);
INSERT INTO documents(id, embedding) VALUES (1, '{0,1,2}'), (2, '{1,2,3}'),  (3, '{1,1,1}');
SELECT id FROM documents ORDER BY embedding <-> ARRAY[3,3,3] LIMIT 1;

Enable the extension

To enable the pg_embedding extension, run the following CREATE EXTENSION statement:

CREATE EXTENSION embedding;

Create a table for your vector data

To store your vector data, create a table similar to the following:

CREATE TABLE documents(id INTEGER, embedding REAL[]);

This statement generates a table named documents with an embedding column for storing vector data. Your table and vector column names may differ.

Insert data

To insert vector data, use an INSERT statement similar to the following:

INSERT INTO documents(id, embedding) VALUES (1, '{0,1,2}'), (2, '{1,2,3}'),  (3, '{1,1,1}');

Query

The pg_embedding extension supports Euclidean (L2), Cosine, and Manhattan distance metrics.

Euclidean (L2) distance:

SELECT id FROM documents ORDER BY embedding <-> array[3,3,3] LIMIT 1;

Cosine distance:

SELECT id FROM documents ORDER BY embedding <=> array[3,3,3] LIMIT 1;

Manhattan distance:

SELECT id FROM documents ORDER BY embedding <~> array[3,3,3] LIMIT 1;

where:

  • SELECT id FROM documents selects the id field from all records in the documents table.
  • ORDER BY sorts the selected records in ascending order based on the calculated distances. In other words, records with values closer to the [1.1, 2.2, 3.3] query vector according to the distance metric will be returned first.
  • <->, <=>, and <~> operators define the distance metric, which calculates the distance between the query vector and each row of the dataset.
  • LIMIT 1 limits the result set to one record after sorting.

In summary, the query retrieves the ID of the record from the documents table whose value is closest to the [3,3,3] query vector according to the specified distance metric.

Create an HNSW index

To optimize search behavior, you can add an HNSW index. To create the HNSW index on your vector column, use a CREATE INDEX statement as shown in the following examples. The pg_embedding extension supports indexes for use with Euclidean, Cosine, and Manhattan distance metrics.

Euclidean (L2) distance index:

CREATE INDEX ON documents USING hnsw(embedding) WITH (dims=3, m=3, efconstruction=5, efsearch=5);
SET enable_seqscan = off;
SELECT id FROM documents ORDER BY embedding <-> array[3,3,3] LIMIT 1;

Cosine distance index:

CREATE INDEX ON documents USING hnsw(embedding ann_cos_ops) WITH (dims=3, m=3, efconstruction=5, efsearch=5);
SET enable_seqscan = off;
SELECT id FROM documents ORDER BY embedding <=> array[3,3,3] LIMIT 1;

Manhattan distance index:

CREATE INDEX ON documents USING hnsw(embedding ann_manhattan_ops) WITH (dims=3, m=3, efconstruction=5, efsearch=5);
SET enable_seqscan = off;
SELECT id FROM documents ORDER BY embedding <~> array[3,3,3] LIMIT 1;

Tuning the HNSW algorithm

The following options allow you to tune the HNSW algorithm when creating an index:

  • dims: Defines the number of dimensions in your vector data. This is a required parameter.
  • m: Defines the maximum number of links or "edges" created for each node during graph construction. A higher value increases accuracy (recall) but also increases the size of the index in memory and index construction time.
  • efconstruction: Influences the trade-off between index quality and construction speed. A high efconstruction value creates a higher quality graph, enabling more accurate search results, but a higher value also means that index construction takes longer.
  • efsearch: Influences the trade-off between query accuracy (recall) and speed. A higher efsearch value increases accuracy at the cost of speed. This value should be equal to or larger than k, which is the number of nearest neighbors you want your search to return (defined by the LIMIT clause in your SELECT query).

In summary, to prioritize search speed over accuracy, use lower values for m and efsearch. Conversely, to prioritize accuracy over search speed, use a higher value for m and efsearch. A higher efconstruction value enables more accurate search results at the cost of index build time, which is also affected by the size of your dataset.

How HNSW search works

HNSW is a graph-based approach to indexing multi-dimensional data. It constructs a multi-layered graph, where each layer is a subset of the previous one. During a search, the algorithm navigates through the graph from the top layer to the bottom to quickly find the nearest neighbor. An HNSW graph is known for its superior performance in terms of speed and accuracy.

The search process begins at the topmost layer of the HNSW graph. From the starting node, the algorithm navigates to the nearest neighbor in the same layer. The algorithm repeats this step until it can no longer find neighbors more similar to the query vector.

Using the found node as an entry point, the algorithm moves down to the next layer in the graph and repeats the process of navigating to the nearest neighbor. The process of navigating to the nearest neighbor and moving down a layer is repeated until the algorithm reaches the bottom layer.

In the bottom layer, the algorithm continues navigating to the nearest neighbor until it can't find any nodes that are more similar to the query vector. The current node is then returned as the most similar node to the query vector.

The key idea behind HNSW is that by starting the search at the top layer and moving down through each layer, the algorithm can quickly navigate to the area of the graph that contains the node that is most similar to the query vector. This makes the search process much faster than if it had to search through every node in the graph.

References

  • [1] Dmitry Baranchuk, Artem Babenko, Yury Malkov; Proceedings of the European Conference on Computer Vision (ECCV), 2018, pp. 202-216 link

More Repositories

1

neon

Neon: Serverless Postgres. We separated storage and compute to offer autoscaling, branching, and bottomless storage.
Rust
11,508
star
2

serverless

Connect to Neon PostgreSQL from serverless/worker/edge functions
TypeScript
229
star
3

website

Official docs and website for Neon.
JavaScript
153
star
4

autoscaling

Postgres vertical autoscaling in k8s
Go
126
star
5

yc-idea-matcher

Submit your idea and get a list of similar ideas that YCombinator has invested in in the past.
TypeScript
118
star
6

wsproxy

Go
92
star
7

ask-neon

Chatbot: Search your own knowledge base by semantic similarity
TypeScript
47
star
8

neonctl

Neon CLI tool. The Neon CLI is a command-line interface that lets you manage Neon Serverless Postgres directly from the terminal.
TypeScript
34
star
9

postgres-ai-playground

TypeScript
33
star
10

create-branch-action

GitHub Action to create a new Neon branch
24
star
11

preview-branches-with-vercel

Example project that shows how you can create a branch for every preview deployment on Vercel using GitHub actions
TypeScript
23
star
12

serverless-cfworker-demo

Demo app for @neondatabase/serverless — details at https://blog.cloudflare.com/neon-postgres-database-from-workers/
HTML
21
star
13

helm-charts

neondatabase helm charts
Smarty
20
star
14

naturesnap

TypeScript
18
star
15

postgres

PostgreSQL in Neon
C
17
star
16

cloudflare-drizzle-neon

Example API using Cloudflare Workers, Drizzle ORM and Neon
TypeScript
16
star
17

neonvm

NeonVM: QEMU-based virtualization API and controller for Kubernetes
Go
16
star
18

ping-thing

Ping a Neon Serverless Postgres database using a Vercel Edge Function to see the journey your request makes.
JavaScript
12
star
19

neon-vercel-kysely

Example use of Neon serverless driver on Vercel Edge Functions with Kysely and kysely-codegen
TypeScript
9
star
20

preview-branches-with-fly

A Neon branch for every Fly Preview app
TypeScript
8
star
21

psql-describe

psql's \d (describe) family of commands ported to JavaScript
JavaScript
7
star
22

delete-branch-action

7
star
23

neon-api-python

a Python client for the Neon API
Python
7
star
24

drizzle-overview

Demo Drizzle ORM, Hono & Neon API
TypeScript
7
star
25

github-automations

Scripts that we use to track issues in github's (beta) projects
TypeScript
5
star
26

tokio-epoll-uring

Use io_uring from vanilla tokio.
Rust
5
star
27

delete-branch-by-name-action

Delete Neon database branch by name
4
star
28

postgres-sample-dbs

A collection of sample Postgres databases for learning, testing, and development.
PLpgSQL
4
star
29

rfcs

4
star
30

neon-branches-visualizer

Visualize your Neon Postgres branches
TypeScript
4
star
31

neon_twitter

TypeScript
3
star
32

neon-vercel-rawsql

Example use of Neon serverless driver on Vercel Edge Functions with raw SQL
TypeScript
3
star
33

zenith.tech

JavaScript
3
star
34

examples

TypeScript
2
star
35

aversion

Rust
2
star
36

neon-postgresql-expert

Input for an OpenAI GPT that can answer questions about Neon database and Postgres
Python
2
star
37

neon-hyperdrive

Example use of Neon with Hyperdrive on Cloudflare Workers
TypeScript
2
star
38

meeting-notes

2
star
39

aws-cost-reporter

Create and share AWS Cost and Usage reports in Slack.
Go
2
star
40

mastodon-fly

Dockerfile
2
star
41

devdays2

Neon Developer Days Side Project
JavaScript
2
star
42

zenith-perf-data

Simple collection of zenith performance test runs
HTML
2
star
43

fastapi-apprunner-neon

Create a serverless API using FastAPI, deployed on AWS App Runner and powered by Neon Postgres
Python
2
star
44

lambda-cdk-neon

This is an example API built using AWS Lambda, API Gateway, Secrets Manager and Neon
TypeScript
2
star
45

neon-vercel-http

Example use of Neon serverless driver's experimental HTTP feature on Vercel Edge Functions
TypeScript
1
star
46

neon-vercel-knex

Example use of Neon serverless driver on Vercel Edge Functions with Knex.js
JavaScript
1
star
47

dev-actions

JavaScript
1
star
48

vm-monitor

Rust
1
star
49

restore-neon-branch

Script to restore a Neon branch to a previous state while preserving the same endpoint
TypeScript
1
star
50

neon-google-colab-notebooks

Neon Google Colab Notebooks
Jupyter Notebook
1
star
51

guide-neon-prisma

Example application for Neon Prisma Guide
JavaScript
1
star
52

guide-neon-drizzle

Example application for Neon with Drizzle
TypeScript
1
star
53

s3-scrubber

Rust
1
star
54

zenith-coverage-data

1
star
55

keycloak-example

TypeScript
1
star
56

.github

Public organization profile
1
star
57

latency-dashboard

TypeScript
1
star
58

neon-vercel-zapatos

Example use of Neon serverless driver on Vercel Edge Functions with Zapatos
TypeScript
1
star
59

rust_wal.experimental

Wrap a database frontend in rust based consensus
Rust
1
star
60

neon-ecto-getting-started-app

Neon Ecto Getting Started
Elixir
1
star
61

rustls-split

Rust
1
star
62

pgvector

C
1
star
63

docker-images

Docker images that helps build and test Neon product
Dockerfile
1
star
64

neon-vector-search-openai-notebooks

Jupyter Notebook for Vector Search with Neon and OpenAI
Jupyter Notebook
1
star
65

reset-branch-action

1
star
66

prisma-vercel-load-test

An app that tests prisma on vercel with vercel postgres
CSS
1
star
67

semicolons

Take a string with multiple Postgres SQL statements, separated by semicolons, and split it into its constituent statements
TypeScript
1
star
68

kube-previews-application

Example project that shows how to create a Neon branch for preview environments deployed on Kubernetes using Argo CD
TypeScript
1
star
69

proxy-bench

Benchmarking tools for Neon's Postgres Proxy
Rust
1
star
70

qovery-lifecycle-job

Shell
1
star
71

edge-data-latency

Visualize the latency of databases at the Edge.
TypeScript
1
star