向量数据库技术内核:从存储到检索,拆解其高效运作的秘密

写在前面:我也是“被向量数据库名词轰炸”过的人
说实话,我第一次接触向量数据库的时候,是有点抗拒的。
那会儿各种文章都在说:
- 向量数据库是 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,保留“相对距离关系”。
这也是为什么你会看到很多向量数据库文档里反复强调一句话:
压缩后,相似度计算仍然“足够准确”。
这里的“足够”,非常工程化。
真正的核心:为什么不能暴力算相似度?

「全量暴力搜索 vs ANN 搜索」复杂度对比图
如果你向量数量很少,事情其实很简单。
比如 1 万条向量,你完全可以:
- 对 query 向量
- 和所有向量
- 全量算一遍相似度
- 排序取 topK
但问题是,真实世界里几乎没人这么玩。
一旦数据量上来,全量计算就直接不可接受了。
这也是向量数据库真正开始和传统数据库分道扬镳的地方。
ANN:向量数据库绕不开的“不完美选择”
说句实话,如果你追求的是绝对精确,那向量数据库本身就是错的。
因为它几乎都建立在一个前提之上:
我不追求最优解,我追求一个足够好的近似解。
这就是所谓的 ANN(Approximate Nearest Neighbor)。
我当时第一次意识到这一点的时候,其实挺震惊的。
因为这意味着:
- 向量数据库从设计之初
- 就放弃了“绝对正确”
换来的,是速度和可扩展性。
从工程角度理解:索引到底在干什么?

“全部向量” → “候选集” → “TopK”
如果你把向量数据库当成一个黑盒,很容易迷失在各种算法名词里。
但如果换个角度想:
索引的核心目的,其实只有一个:
尽可能少地看向量,但还能找到差不多对的那几个。
所有 ANN 索引,本质上都在做这件事。
以 HNSW 为例:为什么“图”这么好用?
HNSW 是我个人觉得最“反直觉但又最工程化”的一种索引结构。
它不是树,也不是 hash,而是一张图。
更准确地说,是多层小世界图。
你可以这样理解它:
- 每个向量是一个点
- 相似的向量之间连边
- 上层图稀疏、下层图密集
搜索的时候:
- 从上层快速跳跃
- 慢慢下沉
- 最后在底层精细搜索
这里面有个很重要的工程思想:
先用很便宜的计算,缩小搜索范围;
再用更贵的计算,做精细判断。
为什么向量检索速度能这么快?
这个问题我后来想了很久,最后得出的结论其实很朴素:
向量数据库快,不是因为算得快,而是因为算得少。
它通过:
- 索引结构
- 压缩表示
- 分层搜索
把原本“必须算 1000 万次”的事情,变成:
只算几千次,甚至几百次。
哪怕每次计算稍微复杂一点,整体还是赚的。
再说一个经常被忽略的点:内存结构

「内存 / 缓存 / 磁盘」分层访问示意图
很多人会以为,向量数据库主要瓶颈在 CPU。
但在真实系统里,内存布局和缓存命中率反而非常关键。
一些非常工程但很少被写进文章的事实:
- 向量通常会被按块存储,方便 SIMD
- 热向量和索引节点会尽量常驻内存
- IO 只在必要时发生
这也是为什么很多向量数据库会强调:
内存越大,体验越好
不是营销,是事实。
从存储到检索,一次完整请求发生了什么?
我们把流程串起来看一次。
当你发起一次向量检索请求时,大致会发生:
- query 被转成 embedding
- embedding 被归一化
- 从索引结构中选出候选集合
- 对候选向量做精细相似度计算
- 排序、返回 topK
- 如果有 metadata filter,再做一次过滤
注意一个细节:
真正算“精确相似度”的向量,数量其实很少。
这就是整个系统能跑起来的关键。
为什么向量数据库和“传统数据库 + 插件”不一样?
我一开始也尝试过:
能不能在 MySQL / PostgreSQL 里直接存向量?
答案是:
能,但体验非常差。
原因并不复杂:
- 存储层不是为高维 float 优化的
- 缓存策略不合适
- 没有针对 ANN 的索引结构
向量数据库并不是“多了个字段类型”,
而是从存储到检索路径全部重新设计过的一套系统。
写到这里,说点更现实的
如果你只是:
- 数据量不大
- QPS 很低
- 对延迟不敏感
你未必真的需要一套完整的向量数据库。
但一旦你遇到:
- 向量规模上百万
- 检索要进主流程
- 延迟必须稳定
那你会非常清楚地感受到:
这些“看起来很复杂的设计”,
本质上都是被工程现实逼出来的。
最后:我现在怎么看向量数据库
如果让我用一句话总结向量数据库,我会说:
它不是一项“新技术”,而是一堆老思想在 AI 场景下的极限工程化。
- 高维数据
- 近似搜索
- 空间换时间
- 不追求完美,只追求可用
这些思想其实并不新,但在大模型时代,被推到了一个前所未有的规模。
如果你已经开始在真实项目里用向量数据库,大概率会遇到一个现实问题:
理论都懂了,但怎么把向量、检索、模型训练这几件事真正连起来,反而更麻烦。
尤其是在做 RAG 或大模型应用时,向量数据库往往只是链路中的一环,前后还牵扯到:
- embedding 模型选择
- 数据构建与清洗
- 检索效果评估
- 以及后续的模型微调与对齐
在这种情况下,很多团队会选择先用一些已经把训练和工程流程封装好的工具,把整体链路跑顺,再逐步替换成更定制化的方案。比如像 LLaMA-Factory online这样的工具,已经把模型微调、数据处理、实验配置这些容易出错的工程细节做了封装,对于想快速验证思路、减少重复造轮子的团队来说,会是一个相对省心的起点。
它解决的不是“算法更先进”,而是一个很现实的问题:
让工程师把精力放在真正需要思考的地方,而不是反复踩同样的工程坑。