80数据库(实战:从索引到embedding到内存管理,如何降低80%向量数据库成本)

80数据库(实战:从索引到embedding到内存管理,如何降低80%向量数据库成本)
实战:从索引到embedding到内存管理,如何降低80%向量数据库成本

当前向量数据库的核心应用场景集中于知识库构建,而在此类场景中,向量数据库成本,有时候会占总支出的 ~45%,仅次于 LLM 调用。

怎么优化向量数据库成本就变得尤为关键,所以,今天这篇文章我们以Milvus为代表,聊聊该如何用好Milvus的高级特性以及运维策略,来降低向量数据库的使用成本

01

Milvus 成本维度详解

在生产环境中,Milvus 的成本主要集中在三类资源:实例(cpu+内存)、网络、存储。以 100M 向量、768 维、float32 为例:

成本占比分布(典型生产环境,100M 向量、768 维、float32)━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━█████████████████████████ 实例(cpu+内存)(85-90%)  ~$2,800/月██ 网络(5-10%)                              ~$250/月█ 存储(2-5%)                                ~$100/月━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━总计:~$3,150/月(基于 AWS 标准定价估算)

维度 1:内存(85-90%)

内存之所以贵,不是因为存数据,而是因为索引要跑得快。HNSW/IVF 等索引结构若完全常驻内存,能将延迟压到毫秒级,但同时把账单推高。传统关系数据库可以依靠 B-Tree 索引和磁盘缓存,但向量检索需要执行数百万次浮点运算,一般会将索引结构完全加载到内存中。

内存需求计算公式:

内存需求 = 向量数据大小 × 索引内存倍数         = (N × D × 4 bytes) × 索引倍数实际案例:100M 向量 × 768 维 × 4 bytes × 1.8x (HNSW)         = 307GB × 1.8 = 553GB         → 需要至少 768GB 总内存(含 OS/缓存/峰值冗余)         → AWS r6i.8xlarge (256GB × 3 台) ≈ $2,800/月

内存成本是向量数据库中的成本大头,是成本优化的重点对象,后面将会重点分析。高 QPS 场景(>1000)或频繁索引构建时,还需关注 CPU 使用率,但大多数场景下内存是选型的决定因素。

维度 2:网络(5-10%)

网络成本的核心不是查询返回 TopK 有多少字节,而是是否跨 AZ/跨区域,以及是否返回大字段(比如把原始向量或大文本随结果返回)。生产中常见的优化是:

  • 只返回必要字段(ID/score/必要 metadata)
  • 避免跨区域调用与跨区域副本同步
  • 控制副本策略与同步开销

通过这些优化,网络成本基本都比较可控,不用过度担心。

维度 3:存储(2-5% 的总成本)

存储是 Milvus 成本中占比最低的部分。Milvus 采用存算分离架构,所有向量数据和索引文件持久化在对象存储(S3/MinIO)中,查询时直接从对象存储加载到内存。对象存储价格极低,约为内存的 1/200。

存储成本估算(100M 向量 × 768 维 × float32):

若配置多副本或跨区域备份,存储成本会相应增加,但通常仍控制在 $50-150/月 范围内,不是成本消耗的大头。

02

内存优化策略

2.1 索引优化:选择正确的索引类型降低 4 倍内存

同样存储 1 亿条 768 维 float32 向量,原始数据约 300GB。

  • FLAT/IVF_FLAT 索引 基本等同于原始向量大小,内存需求约 300GB。
  • HNSW 索引 由于额外的图结构开销,通常需要 1.5–2.0 倍内存(约 450–600GB)。
  • IVF_SQ8 索引 通过将 float32 压缩为 uint8,实现 4 倍压缩,内存需求可降至 75–100GB。
  • IVF_PQ 或 DiskANN 在更激进压缩或磁盘索引模式下,内存可进一步降低到 30–60GB。

因此,在相同数据规模下,不同索引之间的内存差距可达到 4–6 倍。许多朋友在初期部署时默认选择 HNSW 或 IVF_FLAT,追求极致的召回率和低延迟,但忽略了成本代价。实际上,通过合理的索引选择和参数调优,可以在保持 95% 以上召回率的前提下,将内存成本降低 70-85%。以下对比基于 Milvus 官方文档和性能测试数据,假设 float32 向量、L2 距离、单内存副本配置:

  • FLAT:无压缩,精度最高但速度最慢,仅适合小规模场景
  • IVF 系列:通过聚类加速查询,IVF_SQ8 是成本优化的最佳平衡点
  • HNSW:查询速度最快但内存开销最大,适合低延迟优先场景
  • DiskANN:磁盘索引,内存占用极低,但需要高性能 SSD 支持

在典型的 RAG 场景中,IVF_SQ8 相比 IVF_FLAT 的召回率通常仅下降 2-3%(从 97% 降至 94-95%),但内存成本降低 70%。对于大多数应用,这种权衡非常划算。如果对于召回率要求不高,还可以采用 IVF_PQ 或者 IVF_RABITQ 这类深度量化的索引来节省内存开销。

2.2 内存与存储优化:Mmap 与分层存储节省 60-80% 内存

Milvus 提供两种技术来降低内存成本:Mmap(milvus 2.3+)和分层存储(milvus 2.6+)。

MMap(Memory-Mapped File)将本地磁盘文件映射到进程的虚拟地址空间,通过 OS 的 Page Cache 实现按需加载。应用程序访问数据时触发 Page Fault,OS 自动从本地磁盘读取 4KB 页面到物理内存。MMap 不能直接映射对象存储,数据必须先从 S3/MinIO 下载到 QueryNode 本地磁盘。因此 MMap 会新增本地存储成本,但相比节省的内存成本,净收益仍然非常可观。

分层存储将本地磁盘从"数据容器"变为"热数据缓存"。数据不再全量下载,而是按需从对象存储拉取并缓存到本地。对象存储层持久化全量数据,成本极低($0.02-0.04/GB/月),本地缓存层仅缓存热数据,容量远小于全量数据。

启动时,仅加载元数据(MB 级别),启动时间缩短至秒级,查询时缓存命中直接返回(<5ms);未命中则从对象存储拉取(50-200ms)并缓存。

Mmap 和分层存储都会使用到本地磁盘,推荐 NVMe SSD(IOPS > 10,000),用来获取更高的性能。

  • MMap:省内存,不省本地磁盘,延迟稳定
  • 分层存储:内存和本地磁盘都省,但缓存未命中时延迟较高

两者的数据流对比:

【传统全加载】对象存储 ──全量加载──→ 内存(100% 常驻)                       ↑                    成本最高【MMap】对象存储 ──全量下载──→ 本地磁盘(100%)──按需加载──→ 内存(10-30%)                       ↑                          ↑                    新增成本                    大幅节省【分层存储】对象存储 ←─按需拉取─→ 本地缓存(10-30%)──按需加载──→ 内存(无要求)   ↑                      ↑                          ↑持久层                  大幅节省                    大幅节省

Mmap 和分层存储方案如何选择:

2.2.1 MMap 配置方法

方式 1:YAML 配置(推荐用于新部署)

编辑 Milvus 配置文件 milvus.yaml,在 queryNode 部分添加:

queryNode:  mmap:    vectorField: true      # 向量数据vectorIndex: true      # 向量索引(最大节省来源!)    scalarField: true      # 标量数据(RAG 场景推荐)    scalarIndex: true      # 标量索引    growingMmapEnabled: false  # 增量数据保持在内存

方式 2:Python SDK 配置(适用于现有 Collection)

from pymilvus import MilvusClientclient = MilvusClient(uri="http://localhost:19530")# 必须先卸载 Collection,才能修改 mmap 属性client.release_collection("my_collection")# 启用 MMapclient.alter_collection_properties(    collection_name="my_collection",    properties={"mmap.enabled": True})# 重新加载(应用 MMap 配置)client.load_collection("my_collection")# 验证配置是否生效print(client.describe_collection("my_collection")["properties"])# 输出: {'mmap.enabled': 'True'}

2.2.2 分层存储配置详解(Milvus 2.6+)

编辑 Milvus 配置文件 milvus.yaml,在 queryNode 部分添加:

queryNode:  segcore:    tieredStorage:      warmup:                                                                                                                                                                # 选项: sync, async, disable                                # 指定分层存储缓存预热的时机。                                                                                                                                       # - "sync": 在 Segment 被视为加载完成之前,数据会先加载到缓存中。                                                                                              # - "disable": 不会主动将数据加载到缓存中,仅在 Search/Query 任务需要时才加载。                                                                                      # 默认值为 "sync",但向量字段默认为 "disable"。                                                                                                                      scalarField: sync                                                                                                                                                    scalarIndex: sync                                                                                                                                                    vectorField: disable # 向量字段原始数据的缓存预热默认关闭。          vectorIndex: sync      memoryHighWatermarkRatio: 0.85   # 内存使用超过 85% 开始淘汰      memoryLowWatermarkRatio: 0.70    # 淘汰到 70% 停止      diskHighWatermarkRatio: 0.80     # 磁盘淘汰高水位      diskLowWatermarkRatio: 0.75      # 磁盘淘汰低水位      evictionEnabled: true            # 必须开启!      backgroundEvictionEnabled: true  # 后台淘汰线程      cacheTtl: 3600                   # 1 小时未访问自动淘汰

2.3 降维策略:从根源上削减存储需求

维度对成本的显著影响

向量维度是成本的基础乘数。内存消耗、存储空间、计算开销都与维度成正比。1536 维的 text-embedding-3-small 相比 384 维的 all-MiniLM-L6-v2,在相同向量数量下内存需求是 4 倍。

降维不仅影响存储成本,还会降低查询时的计算复杂度。余弦相似度计算的时间复杂度为 O(D),768 维向量的相似度计算比 384 维慢一倍。在高 QPS 场景下,降维可以直接提升吞吐量,减少所需的计算节点数量。

Embedding 模型对比表

以下数据基于 OpenAI 和开源模型的官方基准测试,相对成本以 384 维模型为基准(1.0x):

建议先用小数据集(1M 向量)测试不同维度模型的召回率,找到满足业务需求的最小维度,再全量部署。除了选择低维模型,还可以通过后处理技术比如,PCA(主成分分析),Matryoshka Embeddings 来进一步压缩向量维度。

2.4 数据生命周期管理:Compaction + TTL

在 Milvus 的存储模型中,数据采用追加写入(append-only)方式组织。删除操作通常以逻辑删除标记实现,并不会立即回收底层存储空间。如果缺乏生命周期管理,长期运行的系统会逐渐积累无效数据(已删除或过期数据),导致:

  • 存储空间持续增长
  • Compaction 压力增加
  • 查询路径扫描 segment 增多
  • 备份与同步成本同步上升

因此,数据生命周期管理是控制长期 TCO 的必要机制。

机制一:Compaction —— 回收逻辑删除空间

Compaction 通过合并小 segment、清理删除标记,生成新的紧凑 segment,从而释放无效数据占用的存储空间。

适用场景:

  • 高写入 + 高频删除(如商品上下架、内容更新、日志流)
  • Segment 数量持续增加
  • 存储使用率异常增长

不过 Compaction 是一个资源消耗非常高的任务,建议选择在凌晨或者业务低峰期执行。

机制二:TTL(Time to Live)—— 自动过期控制

对于天然具有时效性的数据(如日志、会话记录、新闻、事件流),TTL 是更高效的控制手段。TTL 的作用:

  • 为数据设置生存时间窗口
  • 自动标记超期数据为删除状态
  • 配合 Compaction 最终释放物理空间

TTL 的典型场景:

  • 只需要保留最近 7 天 / 30 天数据
  • 时间衰减型 RAG 系统
  • 实时推荐

03

云上的另一个选择

对于已经在公有云上使用 Milvus 的用户,除了使用前文的优化策略,Milvus原厂提供的公有云托管服务Zilliz Cloud(https://zilliz.com.cn/) 也是一个不错的降本方案。关于 Zilliz Cloud和Milvus的详细对比可以参考:https://zilliz.com.cn/zilliz-vs-milvus,降本的核心原因有两个:

  1. 性能更好的执行引擎 Cardinal,通过开源的向量数据库评测工具 VectorDBBench 可以看到,Zilliz Cloud 整体性能是开源 Milvus 的 3-5 倍,换句话说,开源 Milvus 需要 5 台机器才能达到的性能,Zilliz Cloud一台机器就可以达到。

  1. 0运维成本,不需要自己单独采购机器部署,不需要自己进行繁琐的参数配置,mmap,分层存储,索引优化 这些降本策略,都已经原生配置到Zilliz Cloud实例中。

此外,milvus 和 Zilliz Cloud 的数据和API 接口都是兼容的,迁移成本极低,官方有成熟的迁移工具:https://docs.zilliz.com.cn/docs/via-stage。使用Zilliz Cloud实现向量数据库成本下降的技术策略非常多,后面会再出专门的文章来分享。

80数据库(实战:从索引到embedding到内存管理,如何降低80%向量数据库成本)

04

总结

本文剖析了向量数据库的成本结构,定位了内存这一成本大头,我们可以按照如下步骤来优化Milvus的内存开销:

  1. 先改索引策略 —— 用压缩量化的索引替代默认高内存索引。
  2. 再改加载方式 —— 启用 MMap 或者分层存储,把全量常驻改为按需加载。
  3. 最后改生命周期管理 —— 用 TTL 和 Compaction 控制长期膨胀。

文章版权声明:除非注明,否则均为边学边练网络文章,版权归原作者所有