文档菜单
文档首页
/
MongoDB 手册
/ /

分片集合

在本页

  • 好处
  • 行为
  • 限制
  • 设置您自己的分片索引键值
  • 示例

在版本中5.3.

分片集合将索引文档存储在与索引规范相同的WiredTiger文件中。将集合的文档和索引存储在同一文件中,与常规索引相比,在存储和性能方面提供了好处。

分片集合使用一个分片索引创建。分片索引指定文档的存储顺序。

要创建分片集合,请参阅示例.

重要

向后不兼容的功能

在降级到5.3之前的MongoDB版本之前,您必须删除分片集合。

与无分片集合相比,分片集合具有以下好处

  • 在分片集合上执行查询更快,无需二级索引,例如在分片索引键上的范围扫描和相等比较。

  • 分片集合具有更小的存储大小,这提高了查询和批量插入的性能。

  • 分片集合可以消除对二级TTL(生存时间)索引的需求。

    • 如果指定了expireAfterSeconds字段,则分片索引也是TTL索引。

    • 要用作TTL索引,_id字段必须是支持的日期类型。请参阅TTL索引

    • 如果您将分片索引用作TTL索引,它将提高文档删除性能并减少分片集合的存储大小。

  • 分片集合在插入、更新、删除和查询方面具有额外的性能改进。

    • 所有集合都有一个_id索引

    • 无分片集合将_id索引与文档分开存储。这需要在插入、更新和删除时进行两次写入,并在查询时进行两次读取。

    • 分片集合将索引和文档一起存储在_id值顺序中。这需要在插入、更新和删除时进行一次写入,并在查询时进行一次读取。

聚类集合按照聚类索引键值存储文档。聚类索引键必须是{ _id: 1 }

由于文档只能按一种顺序存储,因此一个集合中只能有一个聚类索引。只有具有聚类索引的集合才按排序顺序存储数据。

您可以在聚类集合中有一个聚类索引并添加二级索引。聚类索引与二级索引不同

  • 只能在创建集合时创建聚类索引。

  • 聚类索引键与集合一起存储。由collStats命令返回的集合大小包括聚类索引大小。

从MongoDB 6.0.7开始,如果存在可用的聚类索引,MongoDB查询规划器在查询规划过程中评估聚类索引与查询中的二级索引。当查询使用聚类索引时,MongoDB执行有界集合扫描

在MongoDB 6.0.7之前,如果聚类集合上存在二级索引且该二级索引可由您的查询使用,则默认情况下查询规划器选择二级索引而不是聚类索引。在MongoDB 6.1及之前版本中,要使用聚类索引,必须提供提示,因为查询优化器不会自动选择聚类索引。

聚类集合限制

  • 聚类索引键必须是{ _id: 1 }

  • 不能将非聚类集合转换为聚类集合,反之亦然。相反,您

    • 使用聚合管道和$out阶段或$merge阶段从集合中读取文档并将其写入另一个集合,使用聚合管道

    • 使用mongodump导出集合数据,并使用mongorestore.

  • 无法隐藏聚集索引。请参阅隐藏索引。

  • 如果聚集集合有次要索引,集合的存储大小会更大。这是因为具有大聚集索引键的聚集集合上的次要索引可能比非聚集集合上的次要索引具有更大的存储大小。

  • 聚集集合可能不是固定集合。

默认情况下,聚集索引的键值是唯一的文档对象标识符。

您可以设置自己的聚集索引键值。您的键

  • 必须包含唯一值。

  • 必须是不可变的。

  • 应该包含顺序递增的值。这不是要求,但可以改善插入性能。

  • 应该尽可能小。

    • 聚集索引支持大小最多为8 MB的键,但更小的聚集索引键最好。

    • 大的聚集索引键会导致聚集集合增加大小,次要索引也会更大。这会减少聚集集合的性能和存储优势。

    • 具有大聚集索引键的聚集集合上的次要索引可能比非聚集集合上的次要索引使用更多空间。

警告

随机生成的键值可能会降低聚集集合的性能。

本节展示了聚集集合的示例。

以下 create 示例添加了一个名为 products分片集合

db.runCommand( {
create: "products",
clusteredIndex: { "key": { _id: 1 }, "unique": true, "name": "products clustered key" }
} )

在示例中,clusteredIndex 指定

  • "key": { _id: 1 },将分片索引键设置为 _id 字段。

  • "unique": true,表示分片索引键值必须唯一。

  • "name": "products clustered key",设置分片索引名称。

以下 db.createCollection() 示例添加了一个名为 stocks分片集合

db.createCollection(
"stocks",
{ clusteredIndex: { "key": { _id: 1 }, "unique": true, "name": "stocks clustered key" } }
)

在示例中,clusteredIndex 指定

  • "key": { _id: 1 },将分片索引键设置为 _id 字段。

  • "unique": true,表示分片索引键值必须唯一。

  • "name": "stocks clustered key",设置分片索引名称。

以下 create 示例添加了一个名为 orders 的聚集集合

db.createCollection(
"orders",
{ clusteredIndex: { "key": { _id: 1 }, "unique": true, "name": "orders clustered key" } }
)

在示例中,clusteredIndex 指定

  • "key": { _id: 1 },将分片索引键设置为 _id 字段。

  • "unique": true,表示分片索引键值必须唯一。

  • "name": "orders clustered key",用于设置聚集索引的名称。

以下示例向 orders 集合添加文档

db.orders.insertMany( [
{ _id: ISODate( "2022-03-18T12:45:20Z" ), "quantity": 50, "totalOrderPrice": 500 },
{ _id: ISODate( "2022-03-18T12:47:00Z" ), "quantity": 5, "totalOrderPrice": 50 },
{ _id: ISODate( "2022-03-18T12:50:00Z" ), "quantity": 1, "totalOrderPrice": 10 }
] )

_id 聚集索引键存储订单日期。

如果您在范围查询中使用 _id 字段,则可以提高性能。例如,以下查询使用 _id$gt 返回订单日期大于给定日期的订单

db.orders.find( { _id: { $gt: ISODate( "2022-03-18T12:47:00.000Z" ) } } )

示例输出

[
{
_id: ISODate( "2022-03-18T12:50:00.000Z" ),
quantity: 1,
totalOrderPrice: 10
}
]

要确定集合是否聚集,请使用 listCollections 命令

db.runCommand( { listCollections: 1 } )

对于聚集集合,您将在输出中看到 clusteredIndex 的详细信息。例如,以下输出显示了 orders 聚集集合的详细信息

...
name: 'orders',
type: 'collection',
options: {
clusteredIndex: {
v: 2,
key: { _id: 1 },
name: 'orders clustered key',
unique: true
}
},
...

v 是索引版本。

返回

更改限制