結論先講

如果你的向量不超過一百萬筆,直接用 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 年主流的選項:

特性PineconeChromaMilvuspgvectorWeaviateQdrant
類型全託管 SaaS本地/嵌入式自建/雲端PG extension自建/雲端自建/雲端
語言API onlyPython-firstGo/PythonSQLGoRust
適合規模任意<100K>1M<1M>100K>100K
查詢語言REST APIPython APIPyMilvusSQLGraphQLREST/gRPC
混合搜尋有(metadata)基本有(搭配全文)(BM25+向量)
定價$0.096/1M vectors/月起免費開源開源 / Zilliz Cloud免費(PG 成本)開源 / WCS開源 / Qdrant Cloud
學習曲線極低中高極低(會 SQL 就行)
生態整合LangChain、LlamaIndexLangChain 原生全部Django/Rails ORMLangChainLangChain

選擇建議速查

  • 個人專案 / 原型開發 → Chroma(pip install 就能用)
  • 已有 PostgreSQL → pgvector(加 extension 就好)
  • 不想管 infra → Pinecone(花錢買省事)
  • 大規模生產環境 → Milvus 或 Qdrant(效能好、可水平擴展)
  • 需要混合搜尋(關鍵字+語意) → Weaviate(BM25 + 向量一起查)

pgvector:當 PostgreSQL 就夠用的時候

pgvector 是我最推薦新手先試的方案。原因很簡單:

  1. 你大概率已經有 PostgreSQL 了
  2. SQL 你本來就會
  3. 可以跟業務資料 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 - 100K200-500ms< 10ms建議建 HNSW
100K - 1M2-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 更經濟。


本系列文章

  1. 資料庫全景:SQL vs NoSQL vs NewSQL
  2. MySQL:為什麼越來越多人覺得它不夠好?
  3. PostgreSQL:為什麼越來越多人轉
  4. NoSQL 什麼時候該用
  5. 資料庫設計:正規化與索引策略
  6. 向量資料庫:RAG 時代的 Embedding 儲存方案(本篇)
  7. 時序資料庫:監控資料用一般 DB 存,你會後悔
  8. MongoDB vs PostgreSQL:什麼時候該用 NoSQL?
  9. 資料庫設計模式:正規化、反正規化、分表的取捨
  10. 擴展策略:讀寫分離與分片
  11. Docker 環境的資料庫管理
  12. 資料庫安全:從連線加密到欄位加密