2020最新MongoDB规范

前言

MongoDB是非关系型数据库的典型表明,DB-Engines Ranking 数据显示,近年来,MongoDB在 NoSQL领域一直独占鳌头。MongoDB是为快速开发互联网应用 而设计的数据库系统,其数据模型和持 久化策略就是为了构建高读/写的性能,而且能够方面的弹性拓展。随着MongoDB的普及和使用量的快 速增加,为了规范使用,便于管理和获取更高的性能,整理此文档。咱们从 数据库设计规范、集合设计 规范、索引设计规范、文档设计规范、API使用规范、链接规范等方面进行阐述和要求。mysql

存储选型

  1. 主要解决大量数据的访问效率问题, 减小mysql 压力。MongoDB内建了多种数据分片的特性,可 以很好的适应大数据量的需求。内建的Sharding分片特性避免系统在数据增加的过程当中遇到性能 瓶颈。
  2. 复杂数据结构,以多种不一样查询条件去查询同一份数据。MongoDB的BSON数据格式很是适合文 档化格式的存储及查询;支持丰富的查询表达式,可轻易查询文档中内嵌的对象和数组及子文档。
  3. 非事务而且关联性集合不强的均可以使用(MongoDB4.0+支持跨Collection事务,MongoDB4.2+支持跨Shard事务)
  4. 无多文档事务性需求及复杂关联检索
  5. 业务快速迭代,需求频繁变更业务
  6. 数据模型不固定,存储格式灵活场景
  7. 单集群读写并发过大没法支撑业务增加
  8. 指望 5 个 9 的数据库高可用场景
更多关注微信公众号"SpringForAll社区"

1、库设计规范

  1. 【强制】数据库命名规范:db_xxxx
  2. 【强制】库名所有小写,禁止使用任何_之外的特殊字符,禁止使用数字打头的库名,如:123_abc算法

    说明:库以文件夹的形式存在,使用特殊字符或其它不规范的命名方式会致使命名混乱
  3. 【强制】数据库名称最多为 64 个字符。
  4. 【强制】在建立新的库前应尽可能评估该库的体积、QPS等,提早与DBA讨论是应该新建一个库仍是专门为该库建立一个新的集群;

2、集合设计规范

  1. 【强制】集合名所有小写,禁止使用任何_之外的特殊字符,禁止使用数字打头的集合名,如:123_abc,禁止system打头; system是系统集合前缀;
  2. 【强制】集合名称最多为64字符;
  3. 【建议】一个库中写入较大的集合会影响其它集合的读写性能,若是业务比较繁忙的集合在一个DB中,建议最多80个集合,同时也要考虑磁盘I/O的性能;
  4. 【建议】若是评估单集合数据量较大,能够将一个大表拆分为多个小表,而后将每个小表存放在独立的库中或者sharding分表;
  5. 【建议】MongoDB的集合拥有"自动清理过时数据"的功能,只需在该集合中文档的时间字段增长一个TTL索引便可实现该功能,但须要注意的是该字段的类型则必须是mongoDate(),必定要结合实际业务设计是否须要;
  6. 【建议】设计轮询集合---集合是否设计为Capped限制集,必定要结合实际业务设计是否须要;sql

    建立集合规则

    不一样的业务场景是可使用不一样的配置;数据库

    db.createCollection("logs",
    { "storageEngine": { "wiredTiger": 
    { "configString": "internal_page_max=16KB,
       leaf_page_max=16KB,leaf_value_max=8KB,os_cache_max=1GB"} } 
    })
    1. 若是是读多写少的表在建立时咱们能够尽可能将 page size 设置的比较小 ,好比 16KB,若是表数据量不大 ("internal_page_max=16KB,leaf_page_max=16KB,leaf_value_max=8KB,os_cache_max=1GB")
    2. 若是这个读多写少的表数据量比较大,能够为其设置一个压缩算法,例如:"block_compressor=zlib, internal_page_max=16KB,leaf_page_max=16KB,leaf_value_max=8KB"
    3. 注意:该zlib压缩算法不要使用,对cpu消耗特别大,若是使用snapp消耗20% cpu,并且使用zlib能消耗90%cpu,甚至100%
    4. 若是是写多读少的表,能够将 leaf_page_max 设置到 1MB,并开启压缩算法,也能够为其制定操做系统层面 page cache 大小的 os_cache_max 值,让它不会占用太多的 page cache 内存,防止影响读操做;数组

      读多写少的表 internal_page_max=16KB 默认为4KB leaf_page_max=16KB 默认为32KB leaf_value_max=8KB 默认为64MB os_cache_max=1GB 默认为0 读多写少的表 并且数据量比较大 block_compressor=zlib 默认为snappy internal_page_max=16KB 默认为4KB leaf_page_max=16KB 默认为32KB leaf_value_max=8KB 默认为64M

3、文档设计规范

  1. 【强制】集合中的 key 禁止使用任何 "_"(下划线)之外的特殊字符。
  2. 【强制】尽可能将一样类型的文档存放在一个集合中,将不一样类型的文档分散在不一样的集合中;相同类型的文档可以大幅度提升索引利用率,若是文档混杂存放则可能会出现查询常常须要全表扫描的状况;
  3. 【建议】禁止使用_id,如:向_id中写入自定义内容;
说明:MongoDB的表与InnoDB类似,都是索引组织表,数据内容跟在主键后,而_id是MongoDB中的默认主键,一旦_id的值为非自增,当数据量达到必定程度以后,每一次写入均可能致使主键的二叉树大幅度调整,这将是一个代价极大的写入, 因此写入就会随着数据量的增大而降低,因此必定不要在_id中写入自定义的内容。
  1. 【建议】尽可能不要让数组字段成为查询条件;
  2. 【建议】若是字段较大,应尽可能压缩存放;
不要存放太长的字符串,若是这个字段为查询条件,那么确保该字段的值不超过1KB;MongoDB的索引仅支持1K之内的字段,若是你存入的数据长度超过1K,那么它将没法被索引
  1. 【建议】尽可能存放统一了大小写后的数据 ;
  2. 【建议】若是评估单集合数据量较大,能够将一个大表拆分为多个小表,而后将每个小表存放在独立的库中或者sharding分表;

4、索引设计规范

  1. 【强制】MongoDB 的组合索引使用策略与 MySQL 一致,遵循"最左原则";
  2. 【强制】索引名称长度不要超过 128 字符
  3. 【强制】应尽可能综合评估查询场景,经过评估尽量的将单列索引并入组合索引以下降因此数量,结合1,2点;
  4. 【建议】优先使用覆盖索引
  5. 【建议】建立组合索引的时候,应评估索引中包含的字段,尽可能将数据基数大(惟一值多的数据)的字段放在组合索引的前面;
  6. 【建议】MongoDB 支持 TTL 索引,该索引可以按你的须要自动删除XXX秒以前的数据并会尽可能选择在业务低峰期执行删除操做;看业务是否须要这一类型索引;
  7. 【建议】在数据量较大的时候,MongoDB 索引的建立是一个缓慢的过程,因此应当在上线前或数据量变得很大前尽可能评估,按需建立会用到的索引;
  8. 【建议】若是你存放的数据是地理位置信息,好比:经纬度数据。那么能够在该字段上添加 MongoDB 支持的地理索引:2d 及 2dsphere,但他们是不一样的,混用会致使结果不许确;

5、API使用规范

  1. 【强制】在查询条件的字段或者排序条件的字段上必须建立索引。
  2. 【强制】查询结果只包含须要的字段,而不查询全部字段。
  3. 【强制】在文档级别更新是原子性的,这意味着一条更新 10 个文档的语句可能在更新 3 个文档后因为某些缘由失败。应用程序必须根据本身的策略来处理这些失败。
  4. 【建议】单个文档的BSON size不能超过16M;
  5. 【建议】禁用不带条件的update、remove或者find语句。
  6. 【建议】限定返回记录条数,每次查询结果不超过 2000 条。若是须要查询 2000 条以上的数据,在代码中使用多线程并发查询。
  7. 【建议】在写入数据的时候,若是你须要实现相似 MySQL 中 INSERT INTO ON DUPLICATE KEY UPDATE 的功能,那么能够选择 upsert() 函数;
  8. 【建议】写入大量数据的时候能够选择使用 batchInsert,但目前 MongoDB 每一次可以接受的最大消息长度为48MB,若是超出48MB,将会被自动拆分为多个48MB的消息;
  9. 【建议】索引中的-1和1是不同的,一个是逆序,一个是正序,应当根据本身的业务场景创建适合的索引排序,须要注意的是{a:1,b:-1} 和 {a:-1,b:1}是同样的;
  10. 【建议】在开发业务的时候尽可能检查本身的程序性能,可使用 explain() 函数检查你的查询执行详情,另外 hint() 函数至关于 MySQL 中的 force index();
  11. 【建议】若是你结合体积大小/文档数固定,那么建议建立 capped(封顶)集合,这种集合的写入性能很是高并没有需专门清理老旧数据,须要注意的是 capped 表不支持remove() 和 update()操做;
  12. 【建议】查询中的某些 操做符可能会致使性能低下,如ne,,exists,,or,尽可能在业务中不要使用;
:由于松散的文档结构致使查询必须遍历每个文档

ne:若是当取反的值为大多数,则会扫描整个索引微信

:可能会致使查询优化器不知道应当使用哪一个索引,因此会常常退化为全表扫描数据结构

nin:全表扫描多线程

:有多少个条件就会查询多少次,最后合并结果集,因此尽量的使用并发

inapp

  1. 【建议】不要一次取出太多的数据进行排序,MongoDB 目前支持对32MB之内的结果集进行排序,若是须要排序,那么请尽可能限制结果集中的数据量;
  2. 【建议】MongoDB 的聚合框架很是好用,可以经过简单的语法实现复杂的统计查询,而且性能也不错;
  3. 【建议】若是须要清理掉一个集合中的全部数据,那么 remove() 的性能是很是低下的,该场景下应当使用 drop();remove() 是逐行操做,因此在删除大量数据的时候性能不好;
  4. 【建议】在使用数组字段作为查询条件的时候,将与覆盖索引无缘;这是由于数组是保存在索引中的,即使将数组字段从须要返回的字段中剔除,这样的索引仍然没法覆盖查询;
  5. 【建议】在查询中若是有范围条件,那么尽可能和定值条件放在一块儿进行过滤,并在建立索引的时候将定值查询字段放在范围查询字段前;

6、链接规范

  1. 【强制】正确链接副本集,副本集提供了数据的保护、高可用和灾难恢复的机制。若是主节点宕 机,其中一个从节点会自动提高为从节点。
  2. 【建议】合理控制链接池的大小,限制链接数资源,可经过Connection String URL中的 maxPoolSize 参数来配置链接池大小。
  3. 【建议】复制集读选项 默认状况下,复制集的全部读请求都发到Primary,Driver可经过设置的Read Preference 来将 读请求路由到其余的节点。
本文由博客一文多发平台 OpenWrite 发布!
相关文章
相关标签/搜索