图片内容中。
1,所有租户共用一个 Collection:所有租户共享一个 Collection,租户特定字段用于过滤。
2,每个租户一个分区:租户共享一个 Collections,但他们的数据存储在不同的分区中。我们可以通过为每个租户分配一个专用分区来隔离数据。
3,基于 Partition Key 的多租户:这是一种可扩展性更强的方案,其中单个 Collections 使用分区 Key 来区分租户。
它们看起来相似,都是“多个租户的数据放在一个大 Collection 里面,然后靠某种标记字段来区分”。但其实这三种方案之间在 性能、隔离性、可扩展性、系统限制 上是有本质区别的。
📌 背景术语解释(先铺垫一下)
Milvus 中的数据组织结构是这样层级的:
Milvus 实例
└── Collection(相当于一张表)
└── Partition(相当于表的分区)
└── Segment(真正存数据的物理单位)
在这个架构下,我们来逐个分析这三种方案。
✅ 方案1:所有租户共用一个 Collection(靠字段过滤)
🧠 逻辑:
- 所有数据都放在一个 Collection(比如
UserData
) - 每条数据里都有一个字段,比如
tenant_id
- 查询时通过
WHERE tenant_id = 'xxx'
过滤
🧰 举例:
你有 1000 个租户,每条数据记录如下:
{
"tenant_id": "tenant_001",
"user_vector": [0.1, 0.2, ...]
}
查询时你要写:
collection.query(..., filter="tenant_id == 'tenant_001'")
✅ 优点:
- 配置简单,Milvus 不需要额外分区逻辑
- 数据插入和管理方式很通用
❌ 缺点:
- 所有租户的数据物理上在一起,查询会扫所有 segment
- 随着租户增加,性能下降(即使有 filter,也还是要访问不相关的 segment)
- 租户之间隔离性很差
✅ 方案2:每个租户一个分区(Partition)
🧠 逻辑:
- 还是一个 Collection,比如
UserData
- 给每个租户建一个分区,名字比如
tenant_001_partition
- 每个租户的数据都放到自己专属的分区里
- 查询时用
partition_names=["tenant_001_partition"]
🧰 举例:
collection.query(..., partition_names=["tenant_001_partition"])
Milvus 内部只会访问这个 partition 中的 segment,不扫别的。
✅ 优点:
- 性能好:查询只访问相关分区,跳过大量无关数据
- 租户间数据物理隔离,安全性更高
- 支持批量插入
❌ 缺点:
- Milvus 有 最大分区数量限制(比如 <= 4096)
- 如果你有很多租户(> 1w),这个方案就 hold 不住了
✅ 方案3:Partition Key 多租户(按字段自动分区)
🧠 逻辑:
- 创建 Collection 时,声明某个字段为
partition key
(比如tenant_id
) - Milvus 会自动按字段值划分分区
- 你无需手动建 partition,系统帮你管理
FieldSchema(name="tenant_id", dtype=DataType.VARCHAR, is_partition_key=True)
🧰 举例:
插入数据时:
{"tenant_id": "tenant_001", "vector": [...]}
系统会自动把这些数据放到 tenant_001 的隐藏分区中。
查询时直接用:
filter="tenant_id == 'tenant_001'"
✅ 优点:
- 非常适合海量租户(>10w)
- 自动分区管理,不用你操心
- 分区粒度和方案2类似,性能也接近
❌ 缺点:
- 当前 Milvus 不支持对 partition-key Collection 做批量插入
- 插入时每条数据都必须显式带上 partition key 字段
- 较新版本才支持(Milvus 2.3+)
🧠 总结对比表
方案 | 结构 | 隔离性 | 查询性能 | 扩展性 | 插入支持 | 管理复杂度 |
---|---|---|---|---|---|---|
共用 Collection + tenant_id 字段 | 所有数据在一起 | 差 | 差 | 高 | 支持 | 简单 |
每租户一个 Partition | 数据物理隔离 | 高 | 好 | 有上限(约 4K) | 支持 | 中等 |
Partition Key 多租户 | 自动按字段分区 | 中高 | 好 | 极高(>10w租户) | 不支持批量 | 简单 |
🔚 容易搞混的原因
这三种都涉及一个字段 tenant_id
来分租户,看起来区别不大。但 “字段过滤” 和 “分区索引级别过滤” 是性能上完全不同的两码事:
- “字段过滤”是后过滤,Milvus 先扫数据再判断是否属于你;
- “分区过滤”是预过滤,Milvus 直接跳过不相关数据段。
所以看起来一样,实际上性能和隔离上差别非常大。