2020最新MongoDB规范
前⾔
MongoDB是⾮关系型数据库的典型代表,DB-Engines Ranking 数据显⽰,近年来,MongoDB在 NoSQL领域⼀直独占鳌头。MongoDB是为快速开发互联⽹应⽤ ⽽设计的数据库系统,其数据模型和持 久化策略就是为了构建⾼读/写的性能,并且可以⽅⾯的弹性拓展。随着MongoDB的普及和使⽤量的快 速增长,为了规范使⽤,便于管理和获取更⾼的性能,整理此⽂档。我们从 数据库设计规范、集合设计 规范、索引设计规范、⽂档设计规范、API使⽤规范、连接规范等⽅⾯进⾏阐述和要求。
存储选型
1. 主要解决⼤量数据的访问效率问题, 减少mysql 压⼒。MongoDB内建了多种数据分⽚的特性,可 以很好的适应⼤数据量的需求。内
建的Sharding分⽚特性避免系统在数据增长的过程中遇到性能 瓶颈。
2. 复杂数据结构,以多种不同查询条件去查询同⼀份数据。MongoDB的BSON数据格式⾮常适合⽂ 档化格式的存储及查询;⽀持丰富
的查询表达式,可轻易查询⽂档中内嵌的对象和数组及⼦⽂档。
3. ⾮事务并且关联性集合不强的都可以使⽤(MongoDB
4.0+⽀持跨Collection事务,MongoDB4.2+⽀持跨Shard事务)
4. ⽆多⽂档事务性需求及复杂关联检索
mongodb和mysql结合5. 业务快速迭代,需求频繁变动业务
6. 数据模型不固定,存储格式灵活场景
7. 单集读写并发过⼤⽆法⽀撑业务增长
8. 期望 5 个 9 的数据库⾼可⽤场景
⼀、库设计规范
1. 【强制】数据库命名规范:db_xxxx
2. 【强制】库名全部⼩写,禁⽌使⽤任何_以外的特殊字符,禁⽌使⽤数字打头的库名,如:123_abc;
说明:库以⽂件夹的形式存在,使⽤特殊字符或其它不规范的命名⽅式会导致命名混乱
3. 【强制】数据库名称最多为 64 个字符。
4. 【强制】在创建新的库前应尽量评估该库的体积、QPS等,提前与DBA讨论是应该新建⼀个库还是专门为该库创建⼀个新的集;⼆、集合设计规范
1. 【强制】集合名全部⼩写,禁⽌使⽤任何_以外的特殊字符,禁⽌使⽤数字打头的集合名,如:123_abc,禁⽌system打头; system
是系统集合前缀;
2. 【强制】集合名称最多为64字符;
3. 【建议】⼀个库中写⼊较⼤的集合会影响其它集合的读写性能,如果业务⽐较繁忙的集合在⼀个DB中,建议最多80个集合,同时也
要考虑磁盘I/O的性能;
4. 【建议】如果评估单集合数据量较⼤,可以将⼀个⼤表拆分为多个⼩表,然后将每⼀个⼩表存放在独⽴的库中或者sharding分表;
5. 【建议】MongoDB的集合拥有"⾃动清理过期数据"的功能,只需在该集合中⽂档的时间字段增加⼀个TTL索引即可实现该功能,但需
要注意的是该字段的类型则必须是mongoDate(),⼀定要结合实际业务设计是否需要;
6. 【建议】设计轮询集合---集合是否设计为Capped限制集,⼀定要结合实际业务设计是否需要;
创建集合规则
不同的业务场景是可以使⽤不同的配置;
{ "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
三、⽂档设计规范
1. 【强制】集合中的 key 禁⽌使⽤任何 "_"(下划线)以外的特殊字符。
2. 【强制】尽量将同样类型的⽂档存放在⼀个集合中,将不同类型的⽂档分散在不同的集合中;相同类型的⽂档能够⼤幅度提⾼索引利
⽤率,如果⽂档混杂存放则可能会出现查询经常需要全表扫描的情况;
3. 【建议】禁⽌使⽤_id,如:向_id中写⼊⾃定义内容;
说明:MongoDB的表与InnoDB相似,都是索引组织表,数据内容跟在主键后,⽽_id是MongoDB中的默认主键,⼀旦_id的值为⾮⾃增,当数据量达到⼀定程度之后,每⼀次写⼊都可能导致主键的⼆叉树⼤幅度调整,这将是⼀个代价极⼤的写⼊, 所以写⼊就会随着数据量的增⼤⽽下降,所以⼀定不要在_id中写⼊⾃定义的内容。
1. 【建议】尽量不要让数组字段成为查询条件;
2. 【建议】如果字段较⼤,应尽量压缩存放;
不要存放太长的字符串,如果这个字段为查询条件,那么确保该字段的值不超过1KB;MongoDB的索引仅⽀持1K以内的字段,如果你存⼊的数据长度超过1K,那么它将⽆法被索引
1. 【建议】尽量存放统⼀了⼤⼩写后的数据 ;
2. 【建议】如果评估单集合数据量较⼤,可以将⼀个⼤表拆分为多个⼩表,然后将每⼀个⼩表存放在独⽴的库中或者sharding分表;
四、索引设计规范
1. 【强制】MongoDB 的组合索引使⽤策略与 MySQL ⼀致,遵循"最左原则";
2. 【强制】索引名称长度不要超过 128 字符
3. 【强制】应尽量综合评估查询场景,通过评估尽可能的将单列索引并⼊组合索引以降低所以数量,结合1,2点;
4. 【建议】优先使⽤覆盖索引
5. 【建议】创建组合索引的时候,应评估索引中包含的字段,尽量将数据基数⼤(唯⼀值多的数据)的字段放在组合索引的前⾯;
6. 【建议】MongoDB ⽀持 TTL 索引,该索引能够按你的需要⾃动删除XXX秒之前的数据并会尽量选择在业务低峰期执⾏删除操作;
看业务是否需要这⼀类型索引;
7. 【建议】在数据量较⼤的时候,MongoDB 索引的创建是⼀个缓慢的过程,所以应当在上线前或数据量变得很⼤前尽量评估,按需创
建会⽤到的索引;
8. 【建议】如果你存放的数据是地理位置信息,⽐如:经纬度数据。那么可以在该字段上添加 MongoDB ⽀持的地理索引:2d 及
2dsphere,但他们是不同的,混⽤会导致结果不准确;
五、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,not,exists,min,or,尽量在业务中不要使⽤;
exists:因为松散的⽂档结构导致查询必须遍历每⼀个⽂档
ne:如果当取反的值为⼤多数,则会扫描整个索引
not:可能会导致查询优化器不知道应当使⽤哪个索引,所以会经常退化为全表扫描
nin:全表扫描:有多少个条件就会查询多少次,最后合并结果集,所以尽可能的使⽤in
13.【建议】不要⼀次取出太多的数据进⾏排序,MongoDB ⽬前⽀持对32MB以内的结果集进⾏排序,如果需要排序,那么请尽量限制结果集中的数据量;
14.【建议】MongoDB 的聚合框架⾮常好⽤,能够通过简单的语法实现复杂的统计查询,并且性能也不错;
15.【建议】如果需要清理掉⼀个集合中的所有数据,那么 remove() 的性能是⾮常低下的,该场景下应当使⽤ drop();remove() 是逐⾏操作,所以在删除⼤量数据的时候性能很差;
16.【建议】在使⽤数组字段做为查询条件的时候,将与覆盖索引⽆缘;这是因为数组是保存在索引中的,即便将数组字段从需要返回的字段中剔除,这样的索引仍然⽆法覆盖查询;
17.【建议】在查询中如果有范围条件,那么尽量和定值条件放在⼀起进⾏过滤,并在创建索引的时候将定值查询字段放在范围查询字段前;
六、连接规范
1. 【强制】正确连接副本集,副本集提供了数据的保护、⾼可⽤和灾难恢复的机制。如果主节点宕 机,其中⼀个从节点会⾃动提升为从
节点。
2. 【建议】合理控制连接池的⼤⼩,限制连接数资源,可通过Connection String URL中的 maxPoolSize 参数来配置连接池⼤⼩。
3. 【建议】复制集读选项 默认情况下,复制集的所有读请求都发到Primary,Driver可通过设置的Read Preference 来将 读请求路由
到其他的节点。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论