对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。
Docs 菜单

保持分片集群的唯一性

仅当唯一索引位于分片键上或包含分片键作为前缀时,分片集群才会跨分片实施唯一约束。本页介绍了如何在对集合分片分片时保持唯一性。

要在已分片的集合上创建唯一索引,请参阅在现有分片集合上创建唯一索引。要实施分片键键值的唯一性,请参阅强制分片键值的唯一性。要对不能作为分片键一部分的字段实施唯一性,请参阅对不是分片键的字段强制执行唯一性。

要对具有唯一性约束的集合重新分片,新的分片键必须满足任何现有唯一索引的唯一索引要求。有关详细信息,请参阅对集合重新分片。

唯一索引可确保索引字段不存储重复值。在分片的集合上,每个分片只能检查自己的数据是否存在重复项,因此,只有当保证具有给定索引键值的每个文档都位于同一分片上时, MongoDB才能在集群中实施约束。将分片键作为索引的前缀即可提供这种保证。

对于范围分片集合,只有以下索引是唯一的:

  • 分片键上的索引

  • 一个复合索引,其中分片键是前缀

  • 默认的 _id索引;但是,如果_id_id 字段不是分片键,则 索引仅对每个分片强制执行唯一性约束。

唯一索引约束意味着:

  • 对于要分片的集合,如果该集合有多个唯一索引,则无法对该集合分片,除非分片键是所有唯一索引的前缀。

  • 对于已分片的集合,除非包含分片键作为前缀,否则无法在其他字段上创建唯一索引。

  • 唯一索引会为缺少索引字段的文档存储空值。缺失的索引字段将被视为 null索引键值的另一个实例。有关详细信息,请参阅唯一单字段索引中缺少文档字段。

以下约束条件也应用:

  • 不能在哈希索引上指定唯一约束。

  • 如果索引键存在排序规则,则只有排序规则很简单, MongoDB才能确保唯一性。

  • 分片键上的唯一索引会强制整个键组合的唯一性,而不是分片键的各个组件的唯一性。

重要

当 _id 字段不是分片键时,分片集群不会在整个集群中对 _id 字段执行唯一性约束。

如果 _id字段不是分片键,则唯一性约束仅应用于存储文档的分片。这意味着两个或多个文档可以具有相同的 _id 值,前提是它们出现在不同的分片上。

示例,考虑一个分片键为 {x: 1}的分片的集合,它跨越两个分片 A 和 B。由于 _id 键不是分片键,因此该集合可能在分片A 中包含 _id 值为 1 的文档以及分片B 中另一个 _id 值为 1 的文档。

如果 _id字段不是分片键, MongoDB希望应用程序确保各分片中 _id 值的唯一性,示例,使用唯一标识符填充 _id字段。

以下示例对 region_id 上的 accounts.names集合进行分片,并对 region_id 和 email 的组合实施唯一性约束。

1

创建计划用作分片键的索引:

db.names.createIndex( { region_id: 1 } )
region_id_1
2

为集合创建唯一索引。分片键作为索引的前缀包含在内:

db.names.createIndex(
{ region_id: 1, email: 1 },
{ unique: true }
)
region_id_1_email_1
3

要对集合分片,运行sh.shardCollection() 方法:

sh.shardCollection( "accounts.names", { region_id: 1 } )
{
collectionsharded: 'accounts.names',
ok: 1,
'$clusterTime': {
clusterTime: Timestamp( { t: 1759260515, i: 58 } ),
signature: {
hash: Binary.createFromBase64( 'AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0 ),
keyId: Long( '0' )
}
},
operationTime: Timestamp( { t: 1759260515, i: 57 } )
}

如果您对包含唯一索引的集合分片,而该索引不包含分片键作为前缀,则在您运行shardCollection 命令时, MongoDB会返回错误。