跳到主要内容
版本:v3.0.x

强制合并压缩 Compatible with Milvus 3.0.x

强制合并的目的是将小而零散的数据段合并为较少而较大的数据段,以提高查询性能和存储效率。本指南介绍了如何使用强制合并压缩。

说明

此功能处于公开预览阶段。请勿在生产环境中使用。

概述

标准压缩通过多对一合并将分段大小保持在所配置的maxSize 附近,但仍会留下无法在不超出限制的情况下进一步合并的中等大小的片段。例如,如下图所示,如果 Collection 有 5 个 2 MB 的分段,而maxSize 为 3 MB,合并任何两个分段都会超出限制,因此标准压缩无法进一步减少分段数量,碎片布局依然存在。

强制合并增加了一个target_size 参数,并支持在可能的情况下,在严格的容差范围内,按照所需的大小重组段。如下图所示,如果指定的target_size 为 4 MB,则可将 5 个 2 MB 的小分段进一步合并为更少的大分段。这样可以减少多余的分段数,支持比默认maxSize 设置更大的目标,而且当目标非常大时,系统可以根据当前硬件和 QueryNode 拓扑选择实用的输出大小和分段数。

要了解使用哪种压缩方法,请参阅常见问题

R8eow3kaqhktokblcmocnvxmneeR8eow3kaqhktokblcmocnvxmnee

强制合并压缩扩展了现有的 CompactionAPI 扩展了一个target_size 参数。它完全向后兼容:不含target_size 的现有编译调用仍可照常工作。

强制合并是异步操作符。虽然在执行过程中会消耗 I/O 和内存资源,但它不会阻塞搜索或查询操作。

使用强制合并压缩

前提条件

  • Milvus 3.0 或更高版本

  • PyMilvus 3.0 或更高版本

全局配置

以下配置参数控制强制合并行为。请在 Milvus 配置文件中或通过环境变量进行设置。

dataCoord:
segment:
maxSize: 512 # Default segment max size (MB).
# Used when target_size is 0 or omitted.
compaction:
maxFullSegmentThreshold: 100
# When segment count exceeds this threshold,
# a faster greedy algorithm is used instead
# of the standard merge algorithm.
forceMerge:
datanodeMemoryFactor: 4.0
# DataNode memory divided by this factor
# determines the the largest segment
# size the system can allow.
querynodeMemoryFactor: 4.0
# Minimum QueryNode memory divided by this
# factor. Used in automatic size calculation
# to ensure merged segments can be loaded.

| 参数

|

默认值

|

说明

| | --- | --- | --- | |

dataCoord.segment.maxSize

|

512

|

默认网段最大大小(MB)。当target_size 为 0 或省略时用作目标值。也是显式target_size 的最小允许值。

| |

dataCoord.compaction.maxFullSegmentThreshold

|

100

|

用于选择算法的段数阈值。当分段数超过此值时,Milvus 会使用更快的贪婪算法进行合并规划。

  • 标准算法(段数 <=dataCoord.compaction.maxFullSegmentThreshold 时使用):产生更优化的合并结果,但计算时间更长。

  • 贪婪算法(在线段数 >dataCoord.compaction.maxFullSegmentThreshold 时使用):以稍差的最优线段分组为代价,更快地完成规划。

| |

dataCoord.compaction.forceMerge.datanodeMemoryFactor

|

4.0

|

数据节点内存除以该系数,可计算出系统允许的最大分段大小。

  • 数值越大,分配给合并的内存就越少,但留给其他数据节点操作的内存就越多,从而提高节点的稳定性。

  • 较小的值允许较大的合并,但会增加内存压力。

  • 例如,默认系数为 4.0,数据节点内存为 16 GB,合并预算为 4 GB。这意味着单次操作中合并的数据段总大小不能超过 4 GB。

| |

dataCoord.compaction.forceMerge.querynodeMemoryFactor

|

4.0

|

最小查询节点内存除以该系数。在自动大小计算 (target_size=max_int64) 过程中使用,以确保合并后的数据段可以被查询节点加载。

  • 数值越大,生成的分段越小,查询节点越容易加载。

  • 较小的值允许较大的分段,但可能会导致内存受限的查询节点加载失败。

  • 例如,默认系数为 4.0,最小的查询节点有 16 GB 内存,自动计算的目标大小不会超过 4 GB。这样可以防止强行合并产生的数据段过大,以至于查询节点无法加载。

|

要将上述更改应用到 Milvus 群集,请按照 "使用 Helm 配置 Milvus"和 "使用 Milvus 操作符配置 Milvus"中的步骤操作

触发强制合并压缩

通过使用target_size 参数调用compact() ,可以触发强制合并压缩。有关参数详情,请参阅下面的参数参考

有三种强制合并压实模式可供选择:

compact("my_collection", target_size=?)

├─ Mode 1: target_size = 0 (or omitted)
│ Uses config maxSize (default 512 MB)
│ Equivalent to standard compaction

├─ Mode 2: target_size = 2048
│ Merges segments to ~2 GB each
│ Must be >= config maxSize

└─ Mode 3: target_size = max_int64
Auto-calculates optimal size based on
segment distribution and node memory

下面举例说明如何使用每种强制合并压实模式。

默认(标准压缩)

from pymilvus import MilvusClient

client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus"
)

# Standard compaction — uses config maxSize (default 512 MB)
job_id = client.compact("target_collection")

明确目标尺寸

# Merge segments to approximately 2 GB each
job_id = client.compact(
"target_collection",
target_size="2048" # The unit is MB
)

自动尺寸计算

# Let Milvus determine the optimal segment size
max_int64 = (1 << 63) - 1
job_id = client.compact(
"target_collection",
target_size=max_int64
)

参数参考

下表解释了参数。

| 参数

|

类型

|

说明

| | --- | --- | --- | |

collection_name

|

字符串

|

必填。要压缩的 Collection 的名称。

| |

target_size

|

int

|

可选。目标数据段大小(以 MB 为单位)。参数值有 3 个选项:

  • 0 或省略:使用配置的dataCoord.segment.maxSize (默认:512 MB)。相当于标准压缩。

  • 显式值:以 MB 为单位将数据段合并为指定大小(例如 2048)。必须大于或等于配置的dataCoord.segment.maxSize

  • **max_int64 ((1 << 63) - 1):**根据当前网段分布和可用节点资源自动计算最佳大小。

|

说明

如果指定的target_size 小于配置的dataCoord.segment.maxSize ,请求将被拒绝并显示错误。

检查压缩进度

强制合并压缩以异步方式运行。使用返回的作业 ID 检查进度:

# Check compaction state
state = client.get_compaction_state(job_id)
print(f"State: {state}")

最佳实践

  • 不要在生产环境中使用强制合并压缩。

  • **大多数情况下使用自动大小计算模式。**将target_size 设置为max_int64 ,让 Milvus 分析你的网段分布和节点资源,以确定最佳大小。除非您有特定的大小要求,否则建议使用这种方法。

  • **考虑性能权衡。**强制合并压缩是一种资源稠密操作。它会读取、合并和重写段数据。将其安排在低流量时段,以尽量减少对查询延迟的影响。

  • **监控之前和之后的段计数。**使用get_compaction_state()list_persistent_segments 验证压缩是否如预期产生了更少、更大的数据段。

常见问题

强制合并与标准压缩有何不同?

这两种类型的压缩操作有不同的目的。

  • 标准压缩(targetSize=0 或省略)是一种尽力而为的增量清理路径。

  • 强制合并(targetSize>0)是一种 Collection 级的重新打包路径,可以产生更少、更大、接近目标的数据段。

关键区别在于合并形状:标准压缩每个任务的合并形状为 m → 1,而强制合并每个分组输入的合并形状为 m → n。这就是为什么强制合并可以解决标准压缩无法解决的分段布局问题。下表比较了这 2 种操作符。

| 尺寸

|

标准压实(默认)

|

强制合并

| | --- | --- | --- | |

API 触发器

|

targetSize=0 (或未设置),无 Major/L0 标志

|

targetSize>0 (MB)

| |

主要目标

|

增量清理明显的碎片;日常维护

|

为搜索和平衡进行全 Collection 合并

| |

数据段大小来源

|

固定的 dataCoord.segment.maxSize(服务器配置)

|

用户 targetSize,然后通过 maxSafeSize 进行安全限制

| |

参数有效性

|

不调整用户大小

|

用户 targetSize 必须 >= dataCoord.segment.maxSize;否则会被拒绝

| |

安全上限

|

仅配置上限

|

maxSafeSize = min(QueryNode mem, DataNode mem) / memory_factor(独立非池化:进一步减半)

| |

合并形状

|

m → 每个任务 1,输出 <= configMaxSize

|

m → n,输出接近目标大小

| |

中段行为

|

可能会永久卡住(例如,两个 60% 的分段不能合法地变成一个 120% 的分段)

|

重新打包 + 分割有效;没有 "卡在 60% 处 "的模式

| |

Collection 扁平化能力

|

有限;重复运行仍可能留下许多中段

|

强大;旨在减少分段数,提高饱和度

| |

拓扑意识

|

|

有;使用 QueryNode/复制/分散布局

| |

读取路径并行性调整

|

|

有效时使用查询节点数/(副本×分片)调整输出数

| |

典型用例

|

写入/删除后的高消耗日常清理

|

基准准备、搜索优化、负载并行性调整

| |

预期范围

|

不期望重新打包整个 Collection

|

旨在实现 Collection 级别的重新打包结果

|

选择指导:

  • 选择标准压缩进行低风险增量清理。

  • 当您明确希望将 Collection 重塑为与搜索和加载行为一致的更少、更大的片段时,请选择强制合并。

强制合并与聚类压缩有何不同?

聚类压缩(is_clustering=True) 基于聚类键在段内重组数据,以改进搜索剪枝。强制合并 (target_size=N) 在不改变数据分布的情况下优化数据段大小。它们的作用不同,但可以一起使用--先运行聚类压缩来组织数据,然后再运行强制合并来合并生成的数据段。

能否在正在查询的 Collection 上运行强制合并?

可以。强制合并以异步方式运行,不会阻塞查询。不过,它会消耗数据节点和磁盘 I/O 资源,因此在压缩期间查询延迟可能会增加。请将强制合并安排在流量较低的时段,以获得最佳效果。

如果我设置的 target_size 小于 maxSize 会发生什么情况?

请求将被拒绝,并显示错误。目标大小必须大于或等于配置的dataCoord.segment.maxSize