当前向量数据库的核心应用场景集中于知识库构建,而在此类场景中,向量数据库成本,有时候会占总支出的 ~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,降本的核心原因有两个:
- 性能更好的执行引擎 Cardinal,通过开源的向量数据库评测工具 VectorDBBench 可以看到,Zilliz Cloud 整体性能是开源 Milvus 的 3-5 倍,换句话说,开源 Milvus 需要 5 台机器才能达到的性能,Zilliz Cloud一台机器就可以达到。
- 0运维成本,不需要自己单独采购机器部署,不需要自己进行繁琐的参数配置,mmap,分层存储,索引优化 这些降本策略,都已经原生配置到Zilliz Cloud实例中。
此外,milvus 和 Zilliz Cloud 的数据和API 接口都是兼容的,迁移成本极低,官方有成熟的迁移工具:https://docs.zilliz.com.cn/docs/via-stage。使用Zilliz Cloud实现向量数据库成本下降的技术策略非常多,后面会再出专门的文章来分享。

04
总结
本文剖析了向量数据库的成本结构,定位了内存这一成本大头,我们可以按照如下步骤来优化Milvus的内存开销:
- 先改索引策略 —— 用压缩量化的索引替代默认高内存索引。
- 再改加载方式 —— 启用 MMap 或者分层存储,把全量常驻改为按需加载。
- 最后改生命周期管理 —— 用 TTL 和 Compaction 控制长期膨胀。