MongoDB中的物化视图
2023-12-26 18:01:32
视图,为查询提供了便利。定义视图时, 可以包含复杂的集合查询逻辑或隐藏敏感信息。构建查询语句时,无需重复构建和维护聚合管道查询中的多个过程。Mongodb查询优化器也可以调整查询管道中的顺序,与视图查询中定义的查询条件一起进行优化。
视图实时返回聚合查询结果,能够获取到最新的数据。但用户或前端应用需要等待数据库实时计算结果。视图返回结果中的部分定义可以预先计算完成,不需要每次进行计算。物化视图可以满足这样的需求。
定义
物化视图,预先将聚合管道查询结果保存到硬盘中,并从硬盘直接读取结果。物化视图是$merge和$out过程的结果典型应用。
两种视图对比
物化视图与普通视图对比,有下面的差异和相同点。
- 物化视图与普通视图,都返回聚合查询的结果。
- 普通视图,实时查询数据库并返回结果,不会将数据保存到硬盘
- 物化视图从硬盘直接读取数据。在聚合查询中,使用$merge和$out命令,将查询结果写入视图。物化视图可能不会实时获得数据,需要考虑定期更新或手动更新。
- 标准视图不可添加删除索引。查询时查询优化器依赖于视图构建时的集合。物化视图可以添加索引,索引数据保存在硬盘上。
- 性能上,物化视图直接从硬盘读取数据,效率高于普通视图。随着聚合管道查询复杂性的增加,这种优势会更加明显。
应用
某烘焙店在2019年一月底,产生了下面的数据
db.bakesales.insertMany( [
{ date: new ISODate("2018-12-01"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
{ date: new ISODate("2018-12-02"), item: "Cake - Peanut Butter", quantity: 5, amount: new NumberDecimal("90") },
{ date: new ISODate("2018-12-02"), item: "Cake - Red Velvet", quantity: 10, amount: new NumberDecimal("200") },
{ date: new ISODate("2018-12-04"), item: "Cookies - Chocolate Chip", quantity: 20, amount: new NumberDecimal("80") },
{ date: new ISODate("2018-12-04"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
{ date: new ISODate("2018-12-05"), item: "Pie - Key Lime", quantity: 3, amount: new NumberDecimal("60") },
{ date: new ISODate("2019-01-25"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
{ date: new ISODate("2019-01-25"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
{ date: new ISODate("2019-01-26"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
{ date: new ISODate("2019-01-26"), item: "Cookies - Chocolate Chip", quantity: 12, amount: new NumberDecimal("48") },
{ date: new ISODate("2019-01-26"), item: "Cake - Carrot", quantity: 2, amount: new NumberDecimal("36") },
{ date: new ISODate("2019-01-26"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
{ date: new ISODate("2019-01-27"), item: "Pie - Chocolate Cream", quantity: 1, amount: new NumberDecimal("20") },
{ date: new ISODate("2019-01-27"), item: "Cake - Peanut Butter", quantity: 5, amount: new NumberDecimal("80") },
{ date: new ISODate("2019-01-27"), item: "Tarts - Apple", quantity: 3, amount: new NumberDecimal("12") },
{ date: new ISODate("2019-01-27"), item: "Cookies - Chocolate Chip", quantity: 12, amount: new NumberDecimal("48") },
{ date: new ISODate("2019-01-27"), item: "Cake - Carrot", quantity: 5, amount: new NumberDecimal("36") },
{ date: new ISODate("2019-01-27"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
{ date: new ISODate("2019-01-28"), item: "Cookies - Chocolate Chip", quantity: 20, amount: new NumberDecimal("80") },
{ date: new ISODate("2019-01-28"), item: "Pie - Key Lime", quantity: 3, amount: new NumberDecimal("60") },
{ date: new ISODate("2019-01-28"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
] );
现在计划统计每个月这家烘焙店的销售业绩, 包括每个自然月的销售数量和销售额。
构建物化视图
定义方法updateMonthlySales, 要求产生将每个月的销售统计信息放入视图。接受参数开始时间,用户指定开始时间,统计用户指定开始时间前的售卖信息。
var updateMonthlySales = function(startDate) {
db.bakesales.aggregate( [
{ $match: { date: {$gte: startDate}}},
{ $group: { _id: { $dateToString: { format: "%Y-%m", date: "$date"}}, sales_quantity: { $sum: "$quantity"}, sales_amount: { $sum: "$amount"}}},
{ $merge: { into: { coll: "monthlybakesales" }, on: "_id", whenMatched: "replace", whenNotMatched: "insert" }}
])
}
$match方法查询出指定时间后的销售数据
$group方法,按照自然月统计销售数量和销售金额信息
$merge方法,将查询结果放到视图monthlybacksales中。当月销售数据存在时,替换掉视图中当月的数据。当月数据不存在时,将统计后当月销售数据插入视图。
运行方法updateMonthlySales, 产生初始统计数据
updateMonthlySales(new ISODate("1970-01-01"))
查询物化视图
运行updateMonthlySales方法后,数据已经保存到视图monthlybacksales中。
db.monthlybakesales.find().sort("_id")
/* 1 */
{
"_id" : "2018-12",
"sales_quantity" : 41,
"sales_amount" : Decimal128("506")
},
/* 2 */
{
"_id" : "2019-01",
"sales_quantity" : 102,
"sales_amount" : Decimal128("1142")
},
更新物化视图
假设在2019年2月份,该烘焙店产生了下面的新销售数据
db.bakesales.insertMany( [
{ date: new ISODate("2019-01-28"), item: "Cake - Chocolate", quantity: 3, amount: new NumberDecimal("90") },
{ date: new ISODate("2019-01-28"), item: "Cake - Peanut Butter", quantity: 2, amount: new NumberDecimal("32") },
{ date: new ISODate("2019-01-30"), item: "Cake - Red Velvet", quantity: 1, amount: new NumberDecimal("20") },
{ date: new ISODate("2019-01-30"), item: "Cookies - Chocolate Chip", quantity: 6, amount: new NumberDecimal("24") },
{ date: new ISODate("2019-01-31"), item: "Pie - Key Lime", quantity: 2, amount: new NumberDecimal("40") },
{ date: new ISODate("2019-01-31"), item: "Pie - Banana Cream", quantity: 2, amount: new NumberDecimal("40") },
{ date: new ISODate("2019-02-01"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
{ date: new ISODate("2019-02-01"), item: "Tarts - Apple", quantity: 2, amount: new NumberDecimal("8") },
{ date: new ISODate("2019-02-02"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
{ date: new ISODate("2019-02-02"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
{ date: new ISODate("2019-02-03"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") }
] )
为了更新物化视图中的数据,运行方法updateMonthlySales方法
updateMonthlySales(new ISODate("2019-01-01"))
查询更新后的结果
db.monthlybakesales.find().sort("_id")
/* 1 */
{
"_id" : "2018-12",
"sales_quantity" : 41,
"sales_amount" : Decimal128("506")
},
/* 2 */
{
"_id" : "2019-01",
"sales_quantity" : 102,
"sales_amount" : Decimal128("1142")
},
/* 3 */
{
"_id" : "2019-02",
"sales_quantity" : 15,
"sales_amount" : Decimal128("284")
}
文章来源:https://blog.csdn.net/wilsonzane/article/details/135226205
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!