zoukankan      html  css  js  c++  java
  • MongoDB 设计模式集锦

    • 一个好的设计模式可以显著地 提升数据读写的效率降低资源的需求

    • 更多MongoDB的设计模式:

      表现形式类 数据访问类 组织结构类
      列转行 子集 分桶
      文档版本 近似处理 预聚合

    下面开始具体的问题

    问题1:大文档,很多字段,很多索引

    • 索引虽然提高了查询性能,但是在写入时 索引过多 会严重影响性能。
    # 记录电影的各地区的上映日期
    {
    	title: "Dunkirk",
    	...
    	release_HK: "2017/07/20",
    	release_USA: "2017/07/21",
    	release_RUS: "2017/07/20",
    	release_CHN: "2017/09/01",
    	...
    }
    # 需要很多索引
    {release_HK: 1}
    {release_USA: 1}
    {release_RUS: 1}
    {release_CHN: 1}
    ...
    
    • 解决方案:列转行
    {
    	title: "Dunkirk",
    	...
    	releases: [
    		{country: "HK", date: "2017/07/20"},
    		{country: "USA", date: "2017/07/21"},
    		{country: "RUS", date: "2017/07/20"},
    		{country: "CHN", date: "2017/09/01"}
    		...
    	]
    }
    # 索引只需一个组合索引。
    db.movies.createIndex({"releases.country":1,"releases.date":1})
    
    • 列转行 总结:

      场景 痛点 设计模式方案及优点
      产品属性'color', 'size', 'dimensions',...
      多语言(多国家)属性;
      文档中有很多同类型的类似字段;
      会用于组合查询搜索,需要建立很多索引;
      转化为数组,一个索引解决所有的查询问题。
    问题2:Mongo中的灵活模型,如何管理文档的不同版本?

    • Mongo的模型虽然灵活了支持任意的属性增减,但是带来的问题就是数据的不确定性。
    • 解决方案:版本字段
    # 2019.01 版本1.0
    {
    	"_id": ObjectId("5de26f197edd62c5d388babb"),
    	"name": "TJ",
    	"company": "Tapdata",
    }
    
    # 2019.03 版本2.0
    {
    	"_id": ObjectId("5de26f197edd62c5d388babb"),
    	"name": "Tom",
    	"company": "Tapdata",
    	"wechat": "tom23333", # 新增了字段
    	"schema_version": "2.0" # 版本号
    }
    
    • 版本字段 总结:

      场景 痛点 设计模式方案及优点
      任何有版本衍变的数据库。 文档模型格式多,无法知道其合理性;
      升级时需要更新太多文档;
      增加一个版本号字段;
      快速过滤掉不需要升级的文档;
      升级时候对不同版本的文档做不同的处理;
    问题3:统计网页点击流量

    • 每访问一个网页都会产生一次数据库计数更新操作,统计数字准确性并不十分重要

    • 解决方案:近似计算

      # 每次 +1, 加10次。
      for i in range(0,10)
      	{$inc:{views:1}}
      
      # 使用近似计算,十次访问每次随机,随机数触发一次 + 10。
      # 近似地每隔 10次(或n次)写一次。
      for i in range(0,10)
        if random(0,9) == 0
          increment by 10
      
    • 近似计算 总结:

      场景 痛点 设计模式方案及优点
      网页计数
      各种结果不需要准确的排名。
      写入太频繁,消耗系统资源。 间隔写入,每隔 10次或100次,大量减少写入需求。
    问题4:业绩排名,游戏排名,商品统计等精确排名

    • 解决方案:预聚合字段 $inc

      {
      	id: 1003,
      	product: "Bike",
      	quantitiy:200394,  # 库存
      	daily_sales:40,    # 日销量
      	weekly_sales:302,  # 周销量
      	monthly_sales:1420,# 月销量
      }
      
      db.invertory.update(
      	{id: 1003},
      	{$inc:{
      		quantity:-1,
      		daily_sales:1,
      		weekly_sales:1,
      		monthly_sales:1
      	}}
      )
      
    • 预聚合 总结:

      场景 痛点 设计模式方案及优点
      准确排名
      排行榜
      商品热销榜,某商品的日销量/周销量/月销量
      电影排行,观影人次场次统计
      聚合计算消耗资源多,计算时间长。 模型中直接增加统计字段,每次更新数据时候同时更新统计值。
  • 相关阅读:
    JS数组存储(两个数组相等,一个改变,另一个跟着改变)
    图片404加载失败后如何处理
    为什么重写equals方法,还必须要重写hashcode方法
    Java中HashMap和TreeMap的区别深入理解
    java中String数组和List的互相转化
    log4j重复打印的解决方法
    mysql 允许在唯一索引的字段中出现多个null值
    elasticsearch 常见查询及聚合的JAVA API
    A记录(主机名解析)、CNAME(别名解析)和URL转发(域名转发)
    域名解析中的cname解析和显性URL跳转和隐性URL跳转三者有什么区别
  • 原文地址:https://www.cnblogs.com/sweetXiaoma/p/14596908.html
Copyright © 2011-2022 走看看