适用读者:在纠结"要不要上专用向量库"的人。
前置:S20-J01、S13-A03。
实测环境:numpy(单线程暴力检索),2026-11-05。
覆盖旧文:579(205) 2134(193) 2167(165) 741(136) 584(66) 585(69) = 834 点。
覆盖扩展:E-S20-014(成本估算)。
上一篇:S20-J04 · 微调与意图识别:BERT / LoRA / 双模型路由
下一篇:S20-A02 · 安全与多模态。
1. 一句话结论
"100 万向量能不能用 MySQL 硬扛"取决于 QPS 与延迟要求:暴力检索是 O(N×d),一旦数据放不进缓存就急剧变慢;专用向量库用近似索引换速度。
实测(1536 维,含 top10,numpy 单线程):
| N | 耗时 |
|---|---|
| 10,000 | 24.8 ms |
| 100,000 | 29.9 ms |
| 200,000 | 190.5 ms |
读法:10 万以内还能"贴着内存带宽跑",到 20 万陡然跳变(超出缓存/内存带宽成为瓶颈)。
内存估算:1,000,000 × 1536 × 4B = 5.72 GB(仅向量,未计索引与元数据)。
2. 三条技术路线的边界(E-S20-014)
| 方案 | 适用规模 | 延迟 | 代价 |
|---|---|---|---|
| 暴力检索(MySQL/pgvector 无索引) | ≤ 10 万 | 秒级~百毫秒 | 简单,但随 N 线性恶化 |
| pgvector + HNSW | 百万级 | 十毫秒级 | 需调参、占内存 |
| 专用向量库(Milvus/Qdrant) | 千万级 | 毫秒级 | 多一套系统(S13-A03) |
判据:"QPS × 延迟预算能容忍全表扫描吗?" 不能 → 索引(HNSW/IVF);能且规模小 → 暴力检索足够。
"MySQL 硬扛 100 万"的真实答案:能存,但查询会是"全表扫描 + 逐行算距离"——MySQL 不是按列存向量,实际比 numpy 慢一个量级以上(推断,需按具体实现实测)。
3. 成本三块
| 成本 | 估算方式 |
|---|---|
| 存储 | 向量 5.72 GB/百万(1536 维)+ 原文 |
| 计算 | 检索 QPS × 单次开销;embedding 调用按 token |
| 更新 | 换模型要全量重算 embedding(B02) |
"最容易被忽略的是第三块":换 embedding 模型 = 全量重建——这是运营成本里的大头。
4. 降本四招
| 手段 | 效果 |
|---|---|
| 降维(1536 → 512/768) | 存储与计算按比例下降 |
| 量化(float32 → int8) | 内存降至 1/4(精度略降) |
| 两阶段检索(粗排 + 精排) | 粗排用低成本,精排少量 |
| 缓存高频查询 | 减少重复计算 |
5. 五个误区
| 误区 | 真相 |
|---|---|
| "百万向量 MySQL 也能扛" | 能存不能快查 |
| "加机器就能解决" | 受内存带宽限制 |
| "降维一定掉效果" | 视任务,常可接受 |
| "向量库越贵越好" | 规模不够时是过度设计 |
| "重建索引不用算成本" | 换模型即全量重算 |
6. 自检(架构师版)
- 实测中 N 从 10 万到 20 万发生了什么?
- 三条路线的规模边界?
- 百万向量的内存怎么算?
- 成本三块里哪块最易被忽略?
- 四种降本手段?
7. 下一篇
S20-A02 · 安全与多模态
性能讲完,下一篇讲数据边界:RAG 会不会把不该给的给对方。
本篇属于系列《S20 · AI 应用与工程》。旧文来源:A-579/2134/2167/741/584/585;扩展点 E-S20-014。耗时为 numpy 单线程实测(非 MySQL 实现)。