存储计算数据
应用程序可能需要从数据库中存储的源数据中派生一个值。计算新值可能需要大量的CPU资源,尤其是在大型数据集或需要检查多个文档的情况下。
如果经常请求计算的值,预先将其保存到数据库中会更有效率。当应用程序请求数据时,只需进行一次读取操作。
关于此任务
如果读取操作远多于写入操作,这种计算模式可以降低数据计算的频率。应用程序不需要在每次读取时都计算值,而是将计算值存储起来,并在需要时重新计算。应用程序可以选择在更改计算值源数据的每次写入时重新计算值,或者作为周期性任务的一部分。
注意
使用周期性更新,返回的计算值不一定保证是准确的。然而,如果不需要精确度,这种方法可能值得为了性能改进。
步骤
在此示例中,应用程序显示电影观众和收入信息。用户可以查找特定的电影以及该电影赚了多少钱。
1
插入示例数据
创建screenings
集合
db.screenings.insertMany( [ { theater: "Alger Cinema", location: "Lakeview, OR", movie_title: "Lost in the Shadows", movie_id: 1, num_viewers: 344, revenue: 3440 }, { theater: "City Cinema", location: "New York, NY", movie_title: "Lost in the Shadows", movie_id: 1, num_viewers: 1496, revenue: 22440 }, ] )
2
3
更新计算数据
考虑向 screenings
集合中添加新的放映
db.screenings.insertOne( { theater: "Overland Park Cinema", location: "Boise, ID", movie_title: "Lost in the Shadows", movie_id: 1, num_viewers: 760, revenue: 7600 } )
movies
集合中的计算数据不再反映当前的放映数据。计算数据的更新频率取决于您的应用程序
在低写环境下,计算可以在与
screenings
数据的任何更新一起进行。在写操作更频繁的环境中,计算可以在定义的间隔内进行(例如每小时一次)。在
screenings
中的源数据不受对movies
集合的写操作的影响,因此您可以随时运行计算。
要基于screenings数据更新计算数据,您可以定期运行以下聚合操作:
db.screenings.aggregate( [ { $group: { _id: "$movie_id", total_viewers: { $sum: "$num_viewers" }, total_revenue: { $sum: "$revenue" } } }, { $merge: { into: { db: "test", coll: "movies" }, on: "_id", whenMatched: "merge" } } ] )
结果
计算模式可以减少CPU负载并提高应用程序性能。考虑计算模式时,您的应用程序执行相同的计算多次,并且具有高读/写比。