找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2544

积分

0

好友

338

主题
发表于 1 小时前 | 查看: 1| 回复: 0

Milvus向量数据库搜索界面

最近一次小范围调研揭示了一个有趣的现象:在当前主流的RAG知识库应用场景中,向量数据库的成本有时能占到总支出的 ~45%,仅次于大模型(LLM)的调用费用。

因此,如何有效优化向量数据库的成本就成为了一个关键课题。本文将以 Milvus 为例,探讨如何利用其高级特性与合理的运维策略,来实现显著的成本降低。

01 Milvus 成本维度详解

在生产环境中,Milvus 的成本主要集中在这三类资源:实例(CPU + 内存)、网络、存储。我们以 1 亿(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 这类索引结构,若想实现毫秒级延迟,通常需要将其完全常驻内存,而这直接推高了账单。

内存需求计算公式

内存需求 = 向量数据大小 × 索引内存倍数
         = (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、相似度分数、必要的元数据)。
  • 避免跨区域调用和跨区域副本同步。
  • 合理控制副本策略与数据同步开销。

通过这些优化,网络成本通常可以得到有效控制,无需过度担忧。

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

存储是 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) 将本地磁盘文件映射到进程的虚拟地址空间,依靠操作系统的 Page Cache 实现按需加载。数据访问触发缺页中断(Page Fault),系统自动从本地磁盘读取数据到物理内存。MMap 无法直接映射对象存储,数据需先从 S3/MinIO 下载到 QueryNode 的本地磁盘。因此,它会引入额外的本地存储成本,但相较于节省的巨大内存开销,净收益依然非常可观。

分层存储 则将本地磁盘的角色从“数据容器”转变为“热数据缓存”。数据不再全量下载,而是按需从对象存储拉取并缓存在本地。对象存储层持久化全量数据,成本极低($0.02-0.04/GB/月);本地缓存层仅存放热数据,容量远小于全量数据。
系统启动时仅加载元数据(MB级),启动时间缩短至秒级。查询时,若缓存命中则直接返回(延迟 <5ms);若未命中,则从对象存储拉取数据(延迟 50-200ms)并加入缓存。

Mmap 和分层存储都依赖本地磁盘,推荐使用 NVMe SSD(IOPS > 10,000)以获得更好的性能。

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

两者的数据流对比如下:

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

如何选择 Mmap 和分层存储方案?
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 MilvusClient
client = MilvusClient(uri="http://localhost:19530")
# 必须先卸载 Collection,才能修改 mmap 属性
client.release_collection("my_collection")
# 启用 MMap
client.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):
不同文本嵌入模型性能对比表
建议先用小数据集(例如 100 万向量)测试不同维度模型的召回率,找到满足业务需求的最小维度后,再进行全量部署。除了直接选择低维模型,还可以通过主成分分析(PCA)、Matryoshka Embeddings 等后处理技术进一步压缩向量维度。

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

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

  • 存储空间持续增长。
  • 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 的详细对比可参考其官方文档,其降本核心原因主要有两点:

  1. 性能更强的执行引擎 Cardinal:通过开源的向量数据库评测工具 VectorDBBench 可以看到,Zilliz Cloud 的整体性能通常是开源 Milvus 的 3-5 倍。这意味着,开源 Milvus 可能需要 5 台服务器才能达到的性能,Zilliz Cloud 用一台服务器即可实现。
    不同向量搜索系统在固定成本下的延迟与QPS对比图
  2. 近乎为 0 的运维成本:无需自行采购服务器、部署集群,也免去了繁琐的参数调优过程。前文提到的 MMap、分层存储、索引优化等降本策略,在 Zilliz Cloud 实例中已实现原生优化配置。

此外,Milvus 和 Zilliz Cloud 在数据和 API 接口层面完全兼容,迁移成本极低,官方也提供了成熟的迁移工具。关于使用 Zilliz Cloud 实现向量数据库成本优化的更多技术策略,未来会有专门的文章进行分享。

04 总结

本文深入剖析了向量数据库的成本结构,并定位内存为最主要的成本项。我们可以遵循以下步骤来系统性地优化 Milvus 的内存开销:

  1. 先改索引策略 —— 用 IVF_SQ8 等压缩量化索引替代默认的高内存消耗索引(如 HNSW)。
  2. 再改加载方式 —— 根据场景启用 MMap 或分层存储,将数据从“全量常驻内存”转变为“按需加载”。
  3. 最后实施生命周期管理 —— 利用 TTL 和定期的 Compaction 来控制数据的长期膨胀。

如果你已在云上自建 Milvus,但不希望投入过多工程资源进行繁琐的运维,同时追求极致的性价比,那么 Zilliz Cloud 是一个不错的选择。它通过高性能引擎提升单位资源吞吐,并将扩缩容、参数优化等复杂性平台化。在相同的服务等级协议(SLA)下,通常意味着需要更少的计算节点、更低的硬件成本,以及接近零的日常运维负担。

希望这篇实战指南能帮助你更好地驾驭 Milvus,实现成本与性能的平衡。如果你想与更多开发者交流此类Deep Learning基础设施的优化心得,欢迎来云栈社区一起探讨。




上一篇:国产STM32已量产交付,40纳米工艺与双供应链体系解决国产化选型难题
下一篇:Claude Code v2.0.76解锁自动模式:AI编码助手获自主执行代码变更权限
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-26 03:44 , Processed in 0.531935 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表