向量資料庫語意搜尋實戰:從Embedding選型到混合檢索優化

后端开发

向量資料庫為什麼火了?

2026年,從關鍵字搜尋到語意搜尋的範式轉變,正在重塑整個搜尋技術棧。

關鍵字搜尋:使用者搜「蘋果」,只能匹配包含「蘋果」的文件 語意搜尋:使用者搜「蘋果」,能理解你可能想找「iPhone」、「MacBook」或「水果營養」

這種能力的躍遷,核心在於Embedding(向量嵌入)——將文字轉化為高維空間中的數值向量,語意相近的文字在向量空間中距離更近。


Embedding模型選擇

模型 維度 最大Token 多語言 開源 MTEB排名
OpenAI text-embedding-3-large 3072 8191 Top 5
OpenAI text-embedding-3-small 1536 8191 Top 15
BGE-M3 1024 8192 Top 10
Cohere embed-v4 1024 128000 Top 8
GTE-Qwen2 1536 32768 Top 3

選擇建議

追求精度 + 有GPU → GTE-Qwen2 / E5-Mistral-7B
追求性價比 + 快速上線 → OpenAI text-embedding-3-small
中文為主 + 需要開源 → BGE-M3 / GTE-Qwen2
超長文件 → Cohere embed-v4
多語言 + 混合檢索 → BGE-M3

主流向量資料庫對比

特性 Milvus pgvector Qdrant Weaviate Chroma
類型 專用向量資料庫 PostgreSQL擴展 專用向量資料庫 專用向量資料庫 輕量級嵌入式
索引類型 HNSW, IVF_PQ, Flat, SCANN HNSW, IVFFlat HNSW HNSW HNSW
水平擴展 ✅ 原生支援 ✅ 分片 ✅ 分片
混合搜尋 ✅ (SQL)
事務 ✅ ACID
運維複雜度 極低

如何選擇?

已有PostgreSQL基礎設施 → pgvector,零額外運維成本 千萬級以上向量 → Milvus,原生分散式 中等規模 + Rust效能 → Qdrant 快速原型驗證 → Chroma


Spring Boot + pgvector實戰

環境準備

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE documents (
    id BIGSERIAL PRIMARY KEY,
    title VARCHAR(500) NOT NULL,
    content TEXT NOT NULL,
    source VARCHAR(200),
    embedding vector(1536),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_documents_embedding ON documents
    USING hnsw (embedding vector_cosine_ops)
    WITH (m = 16, ef_construction = 64);

向量搜尋Repository

@Repository
public class DocumentVectorRepository {

    private final JdbcTemplate jdbcTemplate;

    public List<DocumentSearchResult> searchSimilar(float[] queryEmbedding, int limit) {
        String vectorStr = Arrays.stream(queryEmbedding)
            .mapToObj(f -> String.format("%.6f", f))
            .collect(Collectors.joining(",", "[", "]"));

        String sql = """
            SELECT id, title, content, source,
                   1 - (embedding <=> ?::vector) AS similarity
            FROM documents
            WHERE embedding IS NOT NULL
            ORDER BY embedding <=> ?::vector
            LIMIT ?
            """;

        return jdbcTemplate.query(sql,
            (rs, rowNum) -> new DocumentSearchResult(
                rs.getLong("id"), rs.getString("title"),
                rs.getString("content"), rs.getString("source"),
                rs.getDouble("similarity")
            ),
            vectorStr, vectorStr, limit
        );
    }
}

索引類型:HNSW、IVF_PQ、Flat

索引類型 查詢速度 召回率 記憶體佔用 適用場景
Flat 100% <10萬條,精度優先
HNSW 高(>95%) 10萬-千萬級,通用首選
IVF_PQ 中(85-95%) 億級,記憶體受限場景
SCANN 最快 Milvus專屬,大規模

混合搜尋:向量搜尋 + BM25關鍵字搜尋

使用者查詢
    ├──→ Embedding → 向量搜尋 → 語意結果(權重α)
    ├──→ 分詞 → BM25搜尋 → 關鍵字結果(權重β)
    └──→ RRF融合 → 最終排序

RRF(Reciprocal Rank Fusion)

public List<DocumentSearchResult> hybridSearch(String query, int limit) {
    float[] embedding = embeddingService.generateEmbedding(query);

    List<DocumentSearchResult> vectorResults = vectorRepository.searchSimilar(embedding, 50);
    List<DocumentSearchResult> keywordResults = fulltextRepository.search(query, 50);

    Map<Long, Double> rrfScores = new HashMap<>();
    int k = 60;

    for (int i = 0; i < vectorResults.size(); i++) {
        rrfScores.merge(vectorResults.get(i).getId(), 1.0 / (k + i + 1), Double::sum);
    }

    for (int i = 0; i < keywordResults.size(); i++) {
        rrfScores.merge(keywordResults.get(i).getId(), 1.0 / (k + i + 1), Double::sum);
    }

    return rrfScores.entrySet().stream()
        .sorted(Map.Entry.<Long, Double>comparingByValue().reversed())
        .limit(limit)
        .collect(Collectors.toList());
}

Rerank重排序

Rerank模型 延遲 精度提升 開源
Cohere Rerank ~100ms +15-25%
bge-reranker-v2-m3 ~50ms +10-20%
Jina Reranker ~80ms +10-15%

典型流程:向量搜尋取Top 50 → Rerank重排 → 回傳Top 10。精度提升15-25%。


成本分析:自建 vs 雲服務

維度 自建Milvus Zilliz Cloud Pinecone pgvector自建
100萬條1536維 ~$50/月 ~$65/月 ~$70/月 ~$30/月
1000萬條1536維 ~$200/月 ~$300/月 ~$350/月 ~$150/月
運維成本
資料安全 完全可控 雲端 雲端 完全可控

建議:起步階段用pgvector(已有PG的情況下),日增向量超過10萬條時考慮Milvus或Zilliz Cloud。


總結

從關鍵字到語意的範式轉變,本質是從「匹配字面」到「理解意圖」的升級。 選擇合適的向量資料庫和Embedding模型,結合混合搜尋和Rerank,才能建構真正好用的語意搜尋系統。

本站提供瀏覽器本地工具,免註冊即可試用 →

#向量数据库#语义搜索#Embedding#Milvus#pgvector