使用子集模式对数据进行分组
MongoDB将经常访问的数据(称为 工作集)保存在RAM中。当数据和索引的工作集增长超过分配的物理RAM时,性能会下降,因为开始进行磁盘访问,并且不再从RAM检索数据。
要解决此问题,您可以对集合分片。但是,分片会产生额外的成本和复杂性,而您的应用程序可能尚未为此做好准备。您可以使用子集模式来减小工作集的大小,而不是对集合分片。
子集模式是一种数据建模技术,用于处理文档中有大量项目但需要频繁访问权限这些项目的一小部分子集的情况。在这种情况下,文档大小通常会导致工作集超过计算机的RAM容量。子集模式减少了常见查询需要从数据库读取的数据量,从而有助于优化性能。
关于此任务
考虑一个电子商务站点,其中有一个产品评论列表,该列表存储在名为 products
的集合中。电子商务站点将具有以下模式的文档插入到 products
集合中:
db.collection('products').insertOne( [ { _id: ObjectId("507f1f77bcf86cd99338452"), name: "Super Widget", description: "This is the most useful item in your toolbox." price: { value: NumberDecimal("119.99"), currency: "USD" }, reviews: [ { review_id: 786, review_author: "Kristina", review_text: "This is indeed an amazing widgt.", published_date: ISODate("2019-02-18") }, { review_id: 785, review_author: "Trina", review_text: "Very nice product, slow shipping.", published_date: ISODate("2019-02-17") }, [...], { review_id: 1, review_author: "Hans", review_text: "Meh, it's ok.", published_date: ISODate("2017-12-06") } ] } ] )
访问产品数据时,您可能只需要最新的评论。以下过程演示了如何将子集模式应用上述模式。
步骤
将子集分成不同的集合。
不必存储产品的所有评论,而是将集合分割为两个集合:一个集合存储访问次数最多的数据,另一个集合存储访问次数最少的数据。这样就可以快速访问权限最相关的数据,而无需加载整个大量。
第一个集合(即 products
集合)包含最常用的数据,例如当前评论:
db.collection('products').insertOne( [ { _id: ObjectId("507f1f77bcf86cd99338452"), name: "Super Widget", description: "This is the most useful item in your toolbox." price: { value: NumberDecimal("119.99"), currency: "USD" }, reviews: [ { review_id: 786, review_author: "Kristina", review_text: "This is indeed an amazing widget.", published_date: ISODate("2019-02-18") }, [...], { review_id: 776, review_author: "Pablo", review_text: "Amazing!", published_date: ISODate("2019-02-15") } ] } ] )
products
集合仅包含 10 条最新评论。这通过仅加载整个数据的一部分或子集来减少工作集。
第二个集合(即 reviews
集合)包含不太常用的数据,例如旧评论:
db.collection('review').insertOne( [ { review_id: 786, review_author: "Kristina", review_text: "This is indeed an amazing widget.", product_id: ObjectId("507f1f77bcf86cd99338452"), published_date: ISODate("2019-02-18") }, { review_id: 785, review_author: "Trina", review_text: "Very nice product, slow shipping.", product_id: ObjectId("507f1f77bcf86cd99338452"), published_date: ISODate("2019-02-17") }, [...], { review_id: 1, review_author: "Hans", review_text: "Meh, it's ok.", product_id: ObjectId("507f1f77bcf86cd99338452"), published_date: ISODate("2017-12-06") } ] )
需要查看其他评论时,您可以随时访问权限reviews
集合。在考虑在何处分割数据时,请将文档中最常用的字段存储在主集合中,将不常用的数据存储在新集合中。
结果
通过使用包含更频繁访问的数据的较小文档,可以减小工作集的总体大小。这样可以缩短磁盘访问权限应用程序所需的最常用信息的时间。
注意
子集模式要求您管理两个集合,而不是一个集合,并在需要收集有关文档而不是子集的全面信息时查询多个数据库。