Corso
La ricerca vettoriale è diventata sempre più popolare negli ultimi anni, grazie ai progressi nell'ecosistema dell'IA generativa e dei Large Language Model.
La ricerca vettoriale è un metodo di recupero delle informazioni in cui documenti e query sono rappresentati come vettori invece che come testo semplice. Questa rappresentazione numerica si ottiene utilizzando una grande rete neurale addestrata in grado di convertire dati non strutturati, come testo, immagini e video, in vettori.
I database relazionali tradizionali non sono ottimizzati per gestire grandi volumi di dati vettoriali. Per questo motivo, negli ultimi anni sono emersi molti database vettoriali open-source e proprietari. Tuttavia, per molte aziende potrebbe non essere ideale avere un database dedicato solo ai vettori, separato dal database principale.
Entra in gioco pgvector, una potente estensione per PostgreSQL che porta le funzionalità di ricerca per similarità vettoriale in uno dei database relazionali più popolari.
In questo tutorial esploreremo le funzionalità di pgvector e mostreremo come può aiutarti nel tuo lavoro.
Che cos'è pgvector?
pgvector è un'estensione open-source per PostgreSQL che aggiunge il supporto per operazioni vettoriali e ricerche per similarità. Ti permette di archiviare, indicizzare ed eseguire query sui dati vettoriali direttamente all'interno del tuo database PostgreSQL.
Questa integrazione porta la potenza delle operazioni vettoriali nella tua infrastruttura PostgreSQL esistente, rendendola un'ottima scelta per applicazioni che coinvolgono embeddings, sistemi di raccomandazione e ricerche per similarità.
Le funzionalità di pgvector includono:
- Archiviazione efficiente di dati vettoriali densi
- Ricerca per similarità veloce utilizzando varie metriche di distanza
- Integrazione con il query planner e i meccanismi di indicizzazione già presenti in PostgreSQL
- Supporto per ricerche dei vicini più prossimi sia esatte che approssimate
L'importanza di pgvector e dei database vettoriali
I database vettoriali sono database specializzati progettati per archiviare e interrogare dati vettoriali multidimensionali. Questa capacità è rilevante nelle moderne applicazioni di machine learning, tra cui sistemi di raccomandazione, recupero di immagini e casi d'uso di elaborazione del linguaggio naturale.

I vettori hanno bisogno di un nuovo tipo di database—immagine fonte.
I database relazionali tradizionali faticano con dati ad alta dimensionalità ed esecuzione efficiente di ricerche per similarità. I database vettoriali, invece, sono specificamente ottimizzati per questi compiti, consentendo un recupero rapido e preciso dei dati in base alla prossimità o somiglianza vettoriale.
Questo approccio consente ricerche basate sulla rilevanza semantica o contestuale, offrendo risultati più significativi rispetto alle ricerche per corrispondenza esatta dei database convenzionali.
Per esempio, un database vettoriale può:
- Cercare brani che risuonano con una determinata melodia in base a melodia e ritmo.
- Scoprire articoli che si allineano a un altro articolo specifico per tema e prospettiva.
- Identificare gadget che rispecchiano le caratteristiche e le recensioni di un determinato dispositivo.
Quindi, come si possono convertire dati non strutturati come testo o immagini in numeri? La risposta sono gli embeddings.
L'embedding è un processo che trasforma dati non strutturati in vettori numerici di dimensione fissa, catturando le semantiche e le relazioni intrinseche all'interno dei dati. Ciò è ottenuto tramite grandi reti neurali che imparano a rappresentare i dati in uno spazio vettoriale continuo, in cui gli elementi simili sono posizionati più vicini tra loro.

Come funziona un database vettoriale? Immagine fonte.
Come usare pgvector: passo dopo passo
In questa sezione vedremo come configurare pgvector, usare le sue funzionalità di base e creare una semplice applicazione integrandola con OpenAI.
Copriamo installazione, operazioni di base, indicizzazione e integrazione con Python e LangChain.
1. Prerequisiti
Per seguire questo tutorial, dovresti avere una conoscenza di base di SQL e PostgreSQL ed essere familiare con la programmazione in Python.
Prima di iniziare, assicurati di avere quanto segue:
- PostgreSQL 11 o successivo installato sul tuo sistema
- Python 3.7 o successivo (per la sezione di integrazione)
- Una chiave API di OpenAI (per l'applicazione di ricerca semantica)
2. Come installare pgvector
1. Per prima cosa, assicurati di avere installati i file di sviluppo di PostgreSQL. Su Ubuntu o Debian, puoi installarli con:
sudo apt-get install postgresql-server-dev-all
Se usi Windows, puoi scaricare l'installer di PostgreSQL dal sito ufficiale.
2. Clona il repository GitHub di pgvector:
git clone https://github.com/pgvector/pgvector.git
3. Compila e installa l'estensione pgvector:
cd pgvector
make
sudo make install
Se usi Windows, assicurati di avere installato il supporto C++ in Visual Studio Code. La documentazione ufficiale di installazione fornisce una procedura passo-passo.
4. Connettiti al tuo database PostgreSQL:
Hai diverse opzioni per connetterti e interagire con il database PostgreSQL: pgAdmin è una delle interfacce più usate. In alternativa, puoi utilizzare pSQL (interfaccia a riga di comando di PostgreSQL) o anche un'estensione di VS Code per PostgreSQL.
5. Dopo esserti connesso al tuo database PostgreSQL, crea l'estensione:
CREATE EXTENSION vector;

Interfaccia pgAdmin
3. Utilizzo di base di pgvector
Ora che abbiamo installato pgvector, esploriamo il suo utilizzo di base.
1. Per configurare il nostro primo database vettoriale in PostgreSQL usando l'estensione pgvector, creiamo una tabella per archiviare i nostri dati vettoriali:
CREATE TABLE items (
id SERIAL PRIMARY KEY,
embedding vector(3)
);
Questo crea una tabella chiamata items con una colonna id e una colonna embedding di tipo vector(3), che archivierà vettori tridimensionali.
2. Ora inseriamo alcuni dati nella nostra tabella:
INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[4,5,6]'), ('[1,1,1]');
3. Ora possiamo eseguire operazioni vettoriali. Per esempio, per trovare il vicino più prossimo del vettore [2,3,4]:
SELECT * FROM items ORDER BY embedding <-> '[2,3,4]' LIMIT 1;
Questa query utilizza l'operatore <->, che calcola la distanza euclidea tra vettori.
4. Possiamo anche usare altre metriche di distanza, come la distanza coseno:
SELECT * FROM items ORDER BY embedding <=> '[2,3,4]' LIMIT 1;
L'operatore <=> calcola la distanza coseno tra vettori.
4. Indicizzazione dei dati vettoriali con pgvector
L'indicizzazione nei database vettoriali, incluso pgvector, è necessaria per migliorare le prestazioni di ricerca, soprattutto quando il dataset cresce.
L'importanza dell'indicizzazione non può essere sopravvalutata, poiché offre diversi vantaggi:
- Primo, migliora significativamente la velocità. Senza un indice, ogni ricerca per similarità richiederebbe una scansione completa della tabella, confrontando il vettore di query con ogni vettore nel database. Questo processo diventa sempre più lungo man mano che i dati crescono. Gli indici creano una struttura che consente ricerche molto più rapide.
- Secondo, l'indicizzazione migliora la scalabilità, consentendo al tuo database di gestire dataset più grandi in modo efficiente. Continuando ad aggiungere vettori, le ricerche correttamente indicizzate mantengono le loro prestazioni.
- Terzo, l'indicizzazione contribuisce all'efficienza delle risorse riducendo il carico su CPU e I/O durante le ricerche. Questo è particolarmente importante per sistemi trafficati o con risorse limitate, garantendo un funzionamento fluido anche in condizioni impegnative.
Sono disponibili due tipi di indici per pgvector: ivfflat e hnsw. Servono entrambi a scopi diversi:
- Indice IVFFlat (Inverted File Flat):
- Adatto a ricerche esatte dei vicini più prossimi
- Divide lo spazio vettoriale in cluster, accelerando le ricerche identificando prima i cluster rilevanti
- Buon equilibrio tra velocità di ricerca e accuratezza
- Indice HNSW (Hierarchical Navigable Small World):
- Progettato per ricerche approssimate dei vicini più prossimi
- Crea una struttura a grafo per una navigazione rapida tra i vettori
- Estremamente veloce, ma potrebbe occasionalmente non trovare il vicino assolutamente più prossimo
Quando usare ciascun indice:
- Usa IVFFlat quando ti servono risultati esatti e puoi tollerare ricerche leggermente più lente
- Usa HNSW quando ti servono ricerche veloci e puoi accettare piccole imprecisioni
1. Creiamo un indice ivfflat:
CREATE INDEX ON items USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
Questo crea un indice utilizzando l'algoritmo IVFFlat, adatto per ricerche esatte dei vicini più prossimi.
2. Per ricerche approssimate dei vicini più prossimi, possiamo usare l'indice hnsw:
CREATE INDEX ON items USING hnsw (embedding vector_l2_ops) WITH (m = 16, ef_construction = 64);
Dopo aver creato un indice, le nostre query lo utilizzeranno automaticamente quando opportuno.
5. Integrazione di pgvector con altri strumenti
Pgvector supporta l'integrazione con alcuni framework, il che rende più semplice interagire con il nostro database vettoriale. Vediamone due utili: Python e LangChain.
Usare pgvector con Python
pgvector può essere facilmente integrato con Python usando la libreria psycopg2. Configuriamo un ambiente Python ed eseguiamo alcune operazioni di base.
1. Per prima cosa, installa le librerie necessarie:
!pip install psycopg2-binary numpy
2. Ora creiamo uno script Python per interagire con il nostro database vettoriale:
import psycopg2
import numpy as np
# Connect to the database
conn = psycopg2.connect("dbname=your_database user=your_username")
cur = conn.cursor()
# Insert a vector
embedding = np.array([1.5, 2.5, 3.5])
cur.execute("INSERT INTO items (embedding) VALUES (%s)", (embedding.tolist(),))
# Perform a similarity search
query_vector = np.array([2, 3, 4])
cur.execute("SELECT * FROM items ORDER BY embedding <-> %s LIMIT 1", (query_vector.tolist(),))
result = cur.fetchone()
print(f"Nearest neighbor: {result}")
conn.commit()
cur.close()
conn.close()
Questo script mostra come inserire un vettore ed eseguire una ricerca per similarità utilizzando Python.
Usare pgvector con LangChain
pgvector può essere integrato anche con LangChain, un framework molto diffuso per sviluppare applicazioni con large language model.
Ecco un semplice esempio di come usare pgvector come vector store in LangChain:
from langchain_postgres.vectorstores import PGVector
from langchain.embeddings.openai import OpenAIEmbeddings
# Set up the connection string and embedding function
connection_string = "postgresql://user:pass@localhost:5432/db_name"
embedding_function = OpenAIEmbeddings()
# Create a PGVector instance
vector_store = PGVector.from_documents(
documents,
embedding_function,
connection_string=connection_string
)
# Perform a similarity search
query = "Your query here"
results = vector_store.similarity_search(query)
Questo esempio presuppone che tu abbia configurato gli embeddings di OpenAI e un elenco di documenti da trasformare in embedding.
6. Creare un'applicazione di esempio con pgvector e OpenAI
Ora costruiamo un semplice motore di ricerca semantica usando pgvector e gli embeddings di OpenAI!
Questa applicazione consentirà agli utenti di cercare in una raccolta di documenti di testo usando query in linguaggio naturale.
import openai
import psycopg2
import numpy as np
# Set up OpenAI API (replace with your actual API key)
openai.api_key = "your_openai_api_key"
# Connect to the database
conn = psycopg2.connect("dbname=your_database user=your_username")
cur = conn.cursor()
# Create a table for our documents
cur.execute("""
CREATE TABLE IF NOT EXISTS documents (
id SERIAL PRIMARY KEY,
content TEXT,
embedding vector(1536)
)
""")
# Function to get embeddings from OpenAI
def get_embedding(text):
response = openai.embeddings.create(input=text, model="text-embedding-ada-002")
return response['data'][0]['embedding']
# Function to add a document
def add_document(content):
embedding = get_embedding(content)
cur.execute("INSERT INTO documents (content, embedding) VALUES (%s, %s)", (content, embedding))
conn.commit()
# Function to search for similar documents
def search_documents(query, limit=5):
query_embedding = get_embedding(query)
cur.execute("""
SELECT content, embedding <-> %s AS distance
FROM documents
ORDER BY distance
LIMIT %s
""", (query_embedding, limit))
return cur.fetchall()
# Add some sample documents
sample_docs = [
"The quick brown fox jumps over the lazy dog.",
"Python is a high-level programming language.",
"Vector databases are essential for modern AI applications.",
"PostgreSQL is a powerful open-source relational database.",
]
for doc in sample_docs:
add_document(doc)
# Perform a search
search_query = "Tell me about programming languages"
results = search_documents(search_query)
print(f"Search results for: '{search_query}'")
for i, (content, distance) in enumerate(results, 1):
print(f"{i}. {content} (Distance: {distance:.4f})")
# Clean up
cur.close()
conn.close()
Questa semplice applicazione mostra come usare pgvector per creare un motore di ricerca semantica.
Esegue l'embedding dei documenti usando il modello di text embedding di OpenAI e li archivia in un database PostgreSQL con pgvector. La funzione di ricerca trova i documenti più simili a una determinata query usando la similarità coseno.
Ottimizzare pgvector per alti volumi di traffico
Vorrai ottimizzare pgvector man mano che la tua applicazione scala. Ecco alcuni suggerimenti a livello generale:
Pooling delle connessioni
Implementa il pooling delle connessioni per ridurre l'overhead. Usa PgBouncer o PgPool-II. Questi strumenti sono utili perché mantengono connessioni al database riutilizzabili.
Ottimizzazione delle prestazioni delle query
Regola i parametri degli indici a runtime. Puoi bilanciare velocità e accuratezza in base alle tue esigenze.
-
Per gli indici IVFFlat, imposta il parametro
probes. Usa 1-5 per la velocità. Usa 10-20 per prestazioni bilanciate. -
Per gli indici HNSW, ottimizza
ef_search. Usa 20-40 per la velocità. Usa 100-200 per l'accuratezza.
Inoltre, puoi usare EXPLAIN ANALYZE per verificare l'uso degli indici. Includi sempre clausole LIMIT nelle query.
Caching
Implementa il caching con Redis o Memcached. Metti in cache i vettori richiesti frequentemente. Usa il vettore di query come chiave della cache. Imposta tempi di scadenza appropriati.
Read replica
Configura le read replica di PostgreSQL per carichi forti in lettura. Instrada le scritture al database primario. Instrada le ricerche vettoriali alle repliche. Usa bilanciatori di carico per la distribuzione automatica.
Configurazione di PostgreSQL
Ottimizza i parametri chiave per i carichi vettoriali:
-
shared_buffers: imposta al 25% della RAM totale -
work_mem: imposta a 64-128 MB per operazioni vettoriali -
random_page_cost: riduci per archiviazione su SSD -
effective_cache_size: imposta al 50-75% della RAM totale
Manutenzione degli indici
Ricostruisci periodicamente gli indici durante i periodi di basso traffico. Esegui VACUUM e ANALYZE. Abilita autovacuum per la manutenzione automatizzata.
Monitoraggio
Tieni traccia della latenza delle query e delle query al secondo. Monitora l'utilizzo del pool di connessioni. Controlla i rapporti di cache hit. Osserva l'uso delle risorse. Configura avvisi per problemi di prestazioni. Abilita pg_stat_statements per identificare le query lente.
pgvector e alternative
Ora confrontiamo pgvector con altri popolari database vettoriali. Questo confronto ti aiuterà a capire le differenze in termini di funzionalità, opzioni di deployment, scalabilità, integrazione e costi tra pgvector e le altre soluzioni disponibili sul mercato.
pgvector vs. Pinecone
Pinecone è un database vettoriale completamente gestito, progettato per alta scalabilità e facilità d'uso.
|
Caratteristica |
pgvector |
Pinecone |
|
Tipo di database |
Estensione per PostgreSQL |
Database vettoriale completamente gestito |
|
Deployment |
Self-hosted |
Basato su cloud |
|
Scalabilità |
Limitata da PostgreSQL |
Altamente scalabile |
|
Integrazione |
Funziona con lo stack PostgreSQL esistente |
Richiede integrazione separata |
|
Costo |
Gratuito, open-source |
Prezzi a consumo |
pgvector è un'ottima scelta per chi vuole sfruttare l'infrastruttura PostgreSQL esistente senza costi aggiuntivi. Allo stesso tempo, Pinecone offre una soluzione gestita altamente scalabile con prezzi a consumo per una maggiore facilità d'uso.
pgvector vs. Milvus
Milvus è un database vettoriale dedicato che offre funzionalità avanzate e alta scalabilità.
|
Caratteristica |
pgvector |
Milvus |
|
Tipo di database |
Estensione per PostgreSQL |
Database vettoriale dedicato |
|
Deployment |
Self-hosted |
Self-hosted o cloud |
|
Scalabilità |
Limitata da PostgreSQL |
Altamente scalabile |
|
Integrazione |
Funziona con lo stack PostgreSQL esistente |
Richiede integrazione separata |
|
Set di funzionalità |
Operazioni vettoriali di base |
Funzionalità avanzate come schema dinamico |
Mentre pgvector fornisce operazioni vettoriali di base all'interno dell'ambiente familiare di PostgreSQL, Milvus offre una soluzione più ricca di funzionalità e scalabile, specificamente pensata per gestire dati vettoriali su larga scala.
pgvector vs. Weaviate
Weaviate è un database vettoriale con storage di oggetti integrato, che offre modellazione dei dati flessibile e scalabilità.
|
Caratteristica |
pgvector |
Weaviate |
|
Tipo di database |
Estensione per PostgreSQL |
Database vettoriale con object storage |
|
Deployment |
Self-hosted |
Self-hosted o cloud |
|
Scalabilità |
Limitata da PostgreSQL |
Progettato per la scalabilità |
|
Integrazione |
Funziona con lo stack PostgreSQL esistente |
Richiede integrazione separata |
|
Modello dati |
Solo vettori |
Oggetti con vettori e proprietà |
La semplicità di pgvector e l'integrazione con PostgreSQL lo rendono adatto agli utenti esistenti che necessitano di funzionalità vettoriali di base. Al contrario, il modello dati più sofisticato e la scalabilità di Weaviate sono indicati per applicazioni complesse che richiedono object storage insieme ai vettori.
Conclusione
pgvector porta potenti funzionalità di ricerca per similarità vettoriale in PostgreSQL, rendendolo un'ottima scelta per gli sviluppatori che vogliono aggiungere funzionalità basate sull'IA alle loro applicazioni basate su PostgreSQL.
In questo tutorial abbiamo esplorato l'installazione, l'uso di base, le capacità di indicizzazione e l'integrazione con Python e LangChain.
Sebbene pgvector non offra la stessa scalabilità e le stesse funzionalità specializzate dei database vettoriali dedicati come Pinecone o Milvus, la sua integrazione fluida con PostgreSQL lo rende un'opzione interessante per molti casi d'uso.
È particolarmente adatto a progetti che già utilizzano PostgreSQL e hanno bisogno di aggiungere funzionalità di ricerca vettoriale senza introdurre un nuovo sistema di database.
Ti invitiamo a provare pgvector nei tuoi progetti. Che tu stia costruendo un sistema di raccomandazione, un motore di ricerca semantica o qualsiasi altra applicazione che richiede ricerche per similarità, pgvector può essere uno strumento prezioso nel tuo toolkit di data science.
Per approfondire, esplora i nostri corsi:
FAQ su pgvector
Devo migrare tutto il mio database per usare pgvector?
No, è un componente aggiuntivo per il tuo database PostgreSQL esistente.
Posso usare pgvector con linguaggi diversi da Python?
Sì, con qualsiasi linguaggio che abbia un adapter per PostgreSQL.
Come posso monitorare le prestazioni delle query di pgvector?
Puoi usare gli strumenti integrati di PostgreSQL come EXPLAIN e ANALYZE per monitorare le prestazioni delle query. Inoltre, estensioni di logging e monitoraggio come pg_stat_statements possono offrire approfondimenti sulle prestazioni delle query e aiutare a identificare i colli di bottiglia.
È possibile combinare la ricerca vettoriale con le query SQL tradizionali?
Sì, pgvector ti consente di combinare la ricerca vettoriale con le query SQL tradizionali. Puoi includere operazioni di similarità vettoriale all'interno delle tue query SQL insieme ad altre condizioni, abilitando ricerche complesse che sfruttano sia dati vettoriali che relazionali.
pgvector può essere usato con altri framework di machine learning oltre a OpenAI?
Sì, pgvector può essere integrato con vari framework e librerie di machine learning. Puoi generare embeddings usando modelli di framework come TensorFlow, PyTorch o Hugging Face, e archiviare e interrogare questi embeddings utilizzando pgvector in PostgreSQL.
Come gestisco gli aggiornamenti di versione di pgvector?
Quando aggiorni pgvector, assicurati di seguire le istruzioni ufficiali di upgrade fornite nella documentazione di pgvector. Esegui il backup dei tuoi dati prima di qualsiasi aggiornamento. Dopo l'upgrade, testa accuratamente la tua applicazione per garantire compatibilità e prestazioni.
pgvector può gestire in modo efficiente vettori ad alta dimensionalità?
Sebbene pgvector possa gestire vettori ad alta dimensionalità, le prestazioni possono essere limitate dalle capacità di PostgreSQL. Per dati con dimensionalità molto elevata, valuta di ottimizzare la tua configurazione PostgreSQL o di esplorare database vettoriali dedicati come Milvus o Pinecone.


