結論先講
如果你的向量不超過一百萬筆,直接用 pgvector 就好。 不用多學一套系統、不用多付一份錢、不用多維護一個服務。PostgreSQL 加個 extension,SQL 直接查,跟現有資料 JOIN 也沒問題。
但如果你的向量量級到千萬甚至上億,或者你需要毫秒級的 ANN 搜尋,那專門的向量資料庫(Milvus、Qdrant、Weaviate)就有它存在的價值。Pinecone 則是「我不想管 infra」的選擇。
什麼是向量資料庫?
先講最基本的:大語言模型(LLM)不是直接「理解」文字,它是把文字轉成一組高維度的數字陣列,這就是 embedding。
# OpenAI embedding 範例
from openai import OpenAI
client = OpenAI()
response = client.embeddings.create(
model="text-embedding-3-small",
input="台北的天氣怎麼樣?"
)
vector = response.data[0].embedding
print(len(vector)) # 1536 維
print(vector[:5]) # [0.0123, -0.0456, 0.0789, ...]一段文字變成 1536 個浮點數。向量資料庫就是專門存這些高維數字陣列,並且能快速找出「最像」的那幾個。
這就是 RAG(Retrieval-Augmented Generation)的核心:把你的文件切塊、轉成 embedding、存進向量資料庫。使用者問問題時,先用向量搜尋找到最相關的文件片段,再餵給 LLM 回答。
為什麼傳統資料庫不行?
你可能會想:「我把 1536 個數字存成 JSON 欄位,然後算距離不就好了?」
技術上可以,但實際上不行:
| 問題 | 說明 |
|---|---|
| 暴力搜尋太慢 | 1 百萬筆向量,每次查詢要算 1 百萬次距離,O(n) 完全不可接受 |
| 索引結構不對 | B-tree 是為一維排序設計的,1536 維的資料用 B-tree 毫無意義 |
| 記憶體效率差 | 1536 維 × float32 = 6KB/向量,100 萬筆就 6GB,沒有專門的壓縮策略很吃資源 |
| 沒有 ANN 演算法 | 專門的向量資料庫用 HNSW、IVF 等近似最近鄰演算法,犧牲一點精確度換幾個數量級的速度 |
關鍵字:ANN(Approximate Nearest Neighbor)。向量搜尋不求「最精確」,只求「夠近而且夠快」。
距離度量:cosine vs L2 vs inner product
在選向量資料庫之前,先搞清楚「相似度」怎麼算:
| 度量 | 公式概念 | 適用場景 | 值域 |
|---|---|---|---|
| Cosine Similarity | 兩向量夾角的餘弦 | 文字語意搜尋(最常用) | -1 到 1 |
| L2 (Euclidean) | 兩點之間直線距離 | 圖片搜尋、推薦系統 | 0 到 ∞ |
| Inner Product | 點積 | 已正規化的向量、MaxMIP | -∞ 到 ∞ |
90% 的 RAG 場景用 cosine similarity 就對了。 OpenAI 和大部分 embedding 模型的輸出都已經正規化(向量長度為 1),這時候 cosine similarity 和 inner product 的結果其實一樣。
import numpy as np
def cosine_similarity(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
# 如果向量已正規化,cosine similarity = inner product
def inner_product(a, b):
return np.dot(a, b)六大向量資料庫比較
這是 2026 年主流的選項:
| 特性 | Pinecone | Chroma | Milvus | pgvector | Weaviate | Qdrant |
|---|---|---|---|---|---|---|
| 類型 | 全託管 SaaS | 本地/嵌入式 | 自建/雲端 | PG extension | 自建/雲端 | 自建/雲端 |
| 語言 | API only | Python-first | Go/Python | SQL | Go | Rust |
| 適合規模 | 任意 | <100K | >1M | <1M | >100K | >100K |
| 查詢語言 | REST API | Python API | PyMilvus | SQL | GraphQL | REST/gRPC |
| 混合搜尋 | 有(metadata) | 基本 | 有 | 有(搭配全文) | 強(BM25+向量) | 有 |
| 定價 | $0.096/1M vectors/月起 | 免費開源 | 開源 / Zilliz Cloud | 免費(PG 成本) | 開源 / WCS | 開源 / Qdrant Cloud |
| 學習曲線 | 低 | 極低 | 中高 | 極低(會 SQL 就行) | 中 | 中 |
| 生態整合 | LangChain、LlamaIndex | LangChain 原生 | 全部 | Django/Rails ORM | LangChain | LangChain |
選擇建議速查
- 個人專案 / 原型開發 → Chroma(pip install 就能用)
- 已有 PostgreSQL → pgvector(加 extension 就好)
- 不想管 infra → Pinecone(花錢買省事)
- 大規模生產環境 → Milvus 或 Qdrant(效能好、可水平擴展)
- 需要混合搜尋(關鍵字+語意) → Weaviate(BM25 + 向量一起查)
pgvector:當 PostgreSQL 就夠用的時候
pgvector 是我最推薦新手先試的方案。原因很簡單:
- 你大概率已經有 PostgreSQL 了
- SQL 你本來就會
- 可以跟業務資料 JOIN(這是專門向量資料庫做不到的)
安裝與基本使用
-- 啟用 extension
CREATE EXTENSION vector;
-- 建表
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
title TEXT,
content TEXT,
embedding vector(1536) -- OpenAI text-embedding-3-small 維度
);
-- 插入資料
INSERT INTO documents (title, content, embedding)
VALUES (
'RAG 教學',
'這是一篇關於 RAG 的文章...',
'[0.0123, -0.0456, ...]'::vector
);
-- 最近鄰搜尋(cosine distance)
SELECT title, content,
1 - (embedding <=> '[0.0789, ...]'::vector) AS similarity
FROM documents
ORDER BY embedding <=> '[0.0789, ...]'::vector
LIMIT 5;<=> 是 cosine distance 運算子,<-> 是 L2 distance,<#> 是 inner product(負值)。
建立索引(重要!)
沒有索引的話,pgvector 會做暴力搜尋。超過幾萬筆一定要建索引:
-- HNSW 索引(推薦,召回率高)
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- IVFFlat 索引(建索引較快,查詢稍慢)
CREATE INDEX ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);效能參考
| 向量數量 | 無索引查詢 | HNSW 查詢 | 建議 |
|---|---|---|---|
| < 10K | < 50ms | 不需要索引 | 暴力搜尋就好 |
| 10K - 100K | 200-500ms | < 10ms | 建議建 HNSW |
| 100K - 1M | 2-5 秒 | < 20ms | 一定要建索引 |
| > 1M | 不可接受 | 開始吃力 | 考慮專門向量 DB |
實戰:用 pgvector 建一個簡單的 RAG
import psycopg2
from openai import OpenAI
client = OpenAI()
def get_embedding(text: str) -> list[float]:
response = client.embeddings.create(
model="text-embedding-3-small",
input=text
)
return response.data[0].embedding
def search_similar(query: str, top_k: int = 5):
query_embedding = get_embedding(query)
conn = psycopg2.connect("postgresql://localhost/mydb")
cur = conn.cursor()
cur.execute("""
SELECT title, content,
1 - (embedding <=> %s::vector) AS similarity
FROM documents
ORDER BY embedding <=> %s::vector
LIMIT %s
""", (str(query_embedding), str(query_embedding), top_k))
results = cur.fetchall()
conn.close()
return results
def ask_with_rag(question: str):
# 1. 搜尋相關文件
docs = search_similar(question, top_k=3)
context = "\n\n".join([f"[{title}]\n{content}" for title, content, _ in docs])
# 2. 組合 prompt 給 LLM
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": f"根據以下資料回答問題:\n\n{context}"},
{"role": "user", "content": question}
]
)
return response.choices[0].message.content
# 使用
answer = ask_with_rag("什麼是向量資料庫?")
print(answer)這就是一個完整的 RAG pipeline——不到 50 行 Python。沒有 LangChain、沒有框架,就是 pgvector + OpenAI API。
什麼時候該上專門的向量資料庫?
| 情境 | 建議 |
|---|---|
| 向量超過一百萬筆 | Milvus / Qdrant |
| 需要即時更新索引(毫秒級) | Qdrant / Weaviate |
| 需要多租戶隔離 | Pinecone / Milvus |
| 需要混合搜尋(BM25 + 向量) | Weaviate |
| 團隊沒有 DevOps 能力 | Pinecone(全託管) |
| 已有 PG,向量 < 100 萬 | pgvector 就好 |
延伸閱讀:如果你對 RAG 架構的完整設計有興趣,可以看 RAG 架構設計,那篇會從 chunking 策略講到 reranking。
常見問題
pgvector 效能真的夠用嗎?
對大部分應用來說,夠了。100 萬筆以下,搭配 HNSW 索引,查詢延遲在 20ms 以內。而且你省下了額外的 infra 成本和維護成本。超過 100 萬筆才需要認真考慮專門的向量資料庫。
Chroma 跟 pgvector 怎麼選?
Chroma 適合快速原型:pip install chromadb 然後 in-memory 就能用,搭配 LangChain 非常方便。但如果你要上生產環境,pgvector 更穩定、更容易備份、更容易跟現有系統整合。
Embedding 模型要選哪個?
2026 年推薦 OpenAI 的 text-embedding-3-small(1536 維,便宜)或 text-embedding-3-large(3072 維,更精確)。開源選項可以看 Cohere embed v4 或 BGE-M3。選模型比選資料庫重要——embedding 品質直接決定搜尋品質。
向量資料庫需要備份嗎?
當然需要。pgvector 的好處是它就是 PostgreSQL,你原本的 pg_dump 備份流程完全適用。專門的向量資料庫各有各的備份機制,這也是選型時要考慮的隱性成本。
可以把向量存在 Redis 裡嗎?
可以,Redis Stack 有 RediSearch 支援向量搜尋。但 Redis 是記憶體資料庫,100 萬筆 1536 維向量大概要 6GB 記憶體。如果你的向量量不大且已有 Redis,是個選項;否則 pgvector 更經濟。