博客 / 詳情

返回

向量數據庫技術內核:從存儲到檢索,拆解其高效運作的秘密

向量數據庫技術內核:從存儲到檢索,拆解其高效運作的秘密

31

寫在前面:我也是“被向量數據庫名詞轟炸”過的人

説實話,我第一次接觸向量數據庫的時候,是有點抗拒的。

那會兒各種文章都在説:

  • 向量數據庫是 AI 時代的“新型基礎設施”
  • 沒有向量數據庫,大模型就跑不起來
  • 它徹底改變了傳統數據庫的範式

結果我真正打開文檔一看,全是:

  • embedding
  • ANN
  • IVF
  • HNSW
  • PQ

名詞密度高到讓我一度懷疑:
這是不是又一個“包裝得很厲害的老技術”?

直到後來我在項目裏真的開始用它、調它、踩坑、看源碼,才慢慢意識到一件事:

向量數據庫真正有價值的地方,不在概念,而在它對「存儲 + 檢索」這件事做了極其激進的工程優化。

這篇文章,我不打算從“是什麼”講起,而是想換個更工程化的視角:

一個向量,從進數據庫到被檢索出來,中間到底經歷了什麼?

一切的起點:為什麼“向量”這件事,本身就很麻煩

在傳統數據庫裏,我們處理的是:

  • int
  • string
  • datetime
  • 少量結構化字段

它們的共同特點是:
可比較、可排序、可精確匹配。

而向量完全不是這麼回事。

一個 embedding,通常是:

  • 384 / 768 / 1536 維
  • float32 或 float16
  • 本身沒有任何“語義”,只是一個數值數組

你沒法説:

這個向量 = 那個向量

你只能説:

這兩個向量,有多像

而“有多像”,通常意味着:

  • 餘弦相似度
  • 內積
  • 歐式距離

到這裏,其實問題已經很清楚了。

向量數據庫的本質問題只有一個:
如何在“巨量高維浮點向量”中,快速找到“足夠相似”的那幾個?

注意我用的是“足夠相似”,而不是“最相似”。

這個細節,後面會反覆出現。

向量存儲:真的只是把 float 存起來嗎?

剛開始我也以為,向量數據庫的“存儲”階段應該很簡單:

不就是一堆 float 數組寫到磁盤上嗎?

後來才發現,這個想法太天真了。

存儲的第一個難題:空間

假設你有:

  • 1000 萬條向量
  • 每條 768 維
  • float32

那光原始數據就是:

1000萬 × 768 × 4 bytes ≈ 30GB

這還沒算索引、元數據、緩存。

所以第一個現實問題就是:

向量數據庫不可能只存“原始向量”。

壓縮,是繞不開的第一步

幾乎所有成熟的向量數據庫,都會在某個階段引入向量壓縮。

但這裏有一個經常被忽略的點:

向量壓縮不是為了省錢,而是為了“讓檢索跑得動”。

常見思路包括:

  • 降低精度(float32 → float16 / int8)
  • Product Quantization(PQ)
  • Scalar Quantization

它們的共同目標只有一個:

用更少的 bit,保留“相對距離關係”。

這也是為什麼你會看到很多向量數據庫文檔裏反覆強調一句話:

壓縮後,相似度計算仍然“足夠準確”。

這裏的“足夠”,非常工程化。

真正的核心:為什麼不能暴力算相似度?

32

「全量暴力搜索 vs ANN 搜索」複雜度對比圖

如果你向量數量很少,事情其實很簡單。

比如 1 萬條向量,你完全可以:

  • 對 query 向量
  • 和所有向量
  • 全量算一遍相似度
  • 排序取 topK

但問題是,真實世界裏幾乎沒人這麼玩。

一旦數據量上來,全量計算就直接不可接受了。

這也是向量數據庫真正開始和傳統數據庫分道揚鑣的地方。

ANN:向量數據庫繞不開的“不完美選擇”

説句實話,如果你追求的是絕對精確,那向量數據庫本身就是錯的。

因為它幾乎都建立在一個前提之上:

我不追求最優解,我追求一個足夠好的近似解。

這就是所謂的 ANN(Approximate Nearest Neighbor)。

我當時第一次意識到這一點的時候,其實挺震驚的。

因為這意味着:

  • 向量數據庫從設計之初
  • 就放棄了“絕對正確”

換來的,是速度和可擴展性。

從工程角度理解:索引到底在幹什麼?

33

“全部向量” → “候選集” → “TopK”

如果你把向量數據庫當成一個黑盒,很容易迷失在各種算法名詞裏。

但如果換個角度想:

索引的核心目的,其實只有一個:
儘可能少地看向量,但還能找到差不多對的那幾個。

所有 ANN 索引,本質上都在做這件事。

以 HNSW 為例:為什麼“圖”這麼好用?

HNSW 是我個人覺得最“反直覺但又最工程化”的一種索引結構。

它不是樹,也不是 hash,而是一張圖。

更準確地説,是多層小世界圖。

你可以這樣理解它:

  • 每個向量是一個點
  • 相似的向量之間連邊
  • 上層圖稀疏、下層圖密集

搜索的時候:

  • 從上層快速跳躍
  • 慢慢下沉
  • 最後在底層精細搜索

這裏面有個很重要的工程思想:

先用很便宜的計算,縮小搜索範圍;
再用更貴的計算,做精細判斷。

為什麼向量檢索速度能這麼快?

這個問題我後來想了很久,最後得出的結論其實很樸素:

向量數據庫快,不是因為算得快,而是因為算得少。

它通過:

  • 索引結構
  • 壓縮表示
  • 分層搜索

把原本“必須算 1000 萬次”的事情,變成:

只算幾千次,甚至幾百次。

哪怕每次計算稍微複雜一點,整體還是賺的。

再説一個經常被忽略的點:內存結構

34

「內存 / 緩存 / 磁盤」分層訪問示意圖

很多人會以為,向量數據庫主要瓶頸在 CPU。

但在真實系統裏,內存佈局和緩存命中率反而非常關鍵。

一些非常工程但很少被寫進文章的事實:

  • 向量通常會被按塊存儲,方便 SIMD
  • 熱向量和索引節點會盡量常駐內存
  • IO 只在必要時發生

這也是為什麼很多向量數據庫會強調:

內存越大,體驗越好

不是營銷,是事實。

從存儲到檢索,一次完整請求發生了什麼?

我們把流程串起來看一次。

當你發起一次向量檢索請求時,大致會發生:

  • query 被轉成 embedding
  • embedding 被歸一化
  • 從索引結構中選出候選集合
  • 對候選向量做精細相似度計算
  • 排序、返回 topK
  • 如果有 metadata filter,再做一次過濾

注意一個細節:

真正算“精確相似度”的向量,數量其實很少。

這就是整個系統能跑起來的關鍵。

為什麼向量數據庫和“傳統數據庫 + 插件”不一樣?

我一開始也嘗試過:

能不能在 MySQL / PostgreSQL 裏直接存向量?

答案是:
能,但體驗非常差。

原因並不複雜:

  • 存儲層不是為高維 float 優化的
  • 緩存策略不合適
  • 沒有針對 ANN 的索引結構

向量數據庫並不是“多了個字段類型”,
而是從存儲到檢索路徑全部重新設計過的一套系統。

寫到這裏,説點更現實的

如果你只是:

  • 數據量不大
  • QPS 很低
  • 對延遲不敏感

你未必真的需要一套完整的向量數據庫。

但一旦你遇到:

  • 向量規模上百萬
  • 檢索要進主流程
  • 延遲必須穩定

那你會非常清楚地感受到:

這些“看起來很複雜的設計”,
本質上都是被工程現實逼出來的。

最後:我現在怎麼看向量數據庫

如果讓我用一句話總結向量數據庫,我會説:

它不是一項“新技術”,而是一堆老思想在 AI 場景下的極限工程化。

  • 高維數據
  • 近似搜索
  • 空間換時間
  • 不追求完美,只追求可用

這些思想其實並不新,但在大模型時代,被推到了一個前所未有的規模。

如果你已經開始在真實項目裏用向量數據庫,大概率會遇到一個現實問題:
理論都懂了,但怎麼把向量、檢索、模型訓練這幾件事真正連起來,反而更麻煩。
尤其是在做 RAG 或大模型應用時,向量數據庫往往只是鏈路中的一環,前後還牽扯到:

  • embedding 模型選擇
    -數據構建與清洗
    -檢索效果評估
    -以及後續的模型微調與對齊

在這種情況下,很多團隊會選擇先用一些已經把訓練和工程流程封裝好的工具,把整體鏈路跑順,再逐步替換成更定製化的方案。
比如像 LLaMA-Factory online這樣的工具,已經把模型微調、數據處理、實驗配置這些容易出錯的工程細節做了封裝,對於想快速驗證思路、減少重複造輪子的團隊來説,會是一個相對省心的起點。
它解決的不是“算法更先進”,而是一個很現實的問題:
讓工程師把精力放在真正需要思考的地方,而不是反覆踩同樣的工程坑。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.