MongoDB 使用规范与限制及最佳实践

MongoDB 灵活文档的优势

  • 灵活库/集合命名及字段增减
  • 同一字段可存储不同类型数据
  • Json 文档可多层次嵌套文档
  • 对于开发而言最自然的表达

MongoDB 灵活文档的烦恼

  • 数据库集合字段名千奇百怪
  • 同一字段数据类型各不一样
  • 业务异常可能写入“脏”数据

1.1 库命名规范

  • 不能为空字符串 ""
  • 不能以 $ 开头
  • 不能包含 . 号 /\
  • 数据库名大小写敏感
  • 数据库名最长为 64 个字符
  • 不能与系统库相同

最佳实践

  • 数据库命名只包含小写英文字符加下划线 _
  • 数据库名含多个单词考虑缩小并以下划线连接
  • 如:package_manager

1.2 集合名规范

  • 不能为空字符串 ""
  • 不能以 system. 系统集合名开头
  • 不因包含 ~!@#%^&*()-+

最佳实践

  • 集合命名只包含下划线和小写英文字母
  • 如:  students_books

1.3 Bson 单文档的大小及嵌套限制

  • 单文档不超过16 MB
  • 嵌套不能超过100 层

如果单条记录超过 16 M 怎么办?

  • 第一种办法:先处理后存储。可以先做压缩,或者也可以对字符进行先哈希,然后再存储,这样大概率就不会超过 16 MB。
  • 第二种方法:通常来说 16 MB 的记录都可以直接写到文本文件里面,然后再将文件存到 MongoDB GridFS 里面或者先业务层处理后存储。

1.4 索引限制

  • 单个集合最多包含 64 个索引
  • 单个索引记录不超过 1024 字节 

  [failIndexKeyTooLong 默认 true 控制是否报错]

  • 多列索引列个数最多不超过 31
  • 前台模式 createIndexes内存限制500 MB

(maxIndexBuildMemoryUsageMegabytes 可调整)

  • 不允许创建多列数组的组合索引

MongoDB 如果索引字段是数组,那我们可以理解为对每个数组元素创建索引。如果要是多个数组字段建组合索引,就意味着它可能会产生笛卡尔级数据量的索引。所以为了避免这种索引的爆炸性增长,需要对此做了相应的一个限制

  • TTL 索引如果是复合索引则过期将会失效

通常你想创建一个 TTL 索引,但创建的时候构建了多个字段的组合索引,那么 TTL 就会失效。

  • Hash 索引只支持单列 【<= 4.4 版本】

哈希索引只支持单例,这个是在 4.4 之前的一个限制,到后面是做了调整,在这里也需要给大家提一下。主要原因在于 4.4 及其以上的 MongoDB 版本其实有很多企业里面都没有使用。

最佳实践  

  • 使用 background 模式批量创建索引

后台建索引意味着它不会阻塞我们的业务的写,否则的话就会加库级别的锁从而造成业务阻塞。当然还有一个情况就是当我们对同一个集合添加多个索引的时候,建议大家用 createIndexes 批量建索引。因为每次创建索引,实际上可以理解 MongoDB 都会去扫描整个集合,通过扫描整个集合去拿到对应字段的记录,然后将这些记录插入到索引文件里面,使用批量建索引只需要扫描一次,如果分开来建索引那么就需要扫描多次,故批量建索引能大大减少对业务的影响。

  • 多列索引尽量不要超过 5 个字段

经验建议,当然 6 个字段也行。有时候要反过来想,当一个索引有 5 、6 个字段或者 7 、8 个字段的时候,应该第一时间要反思业务设计是否合理。当然有些业务场景比较特殊也确实有这种必要性,那该放开限制还的放开。

  • 单个集合索引数量适当控制至 5 个

MongoDB 每次在数据插入更新删除的时候,实际上需要同步的去做索引的变更,所以索引越多,其实对于这些变更来说,它的代价就越大。所以,推荐创建尽量少的索引去满足更多的业务查询。

  • 尽量避免对数组字段创建索引

前面说过,对存储数组的字段创建索引,实际上是多数组每个元素创建索引,同时,字段值更新也同步更新索引字段。所以,当数组元素量非常大的时候比如 1 w,5 w,这个时候的索引代价就会比较大。

1.5 副本集限制

  • 副本集最多含有 50 个节点
  • 副本集只可含 7 个投票节点

为何副本集只可含有 7 个投票节点?

为了提高选举效率、减少心跳网络代价。

1.6 分布式集群限制

  • 分片 key 最大长度不能超过 512 字节
  • 分片 key 索引类型不能是 text 、数组索引和 geo 索引
  • 分片集合单个文档的条件操作必须带分片 key 或 _id 
  • 分片 key 及其值不允许修改( 4.2 版本前不允许修改 key 值,4.4 版本前不许变更 key 字段)

虽然 4.2 版本可以修改分片 key 的值,4.4 版本可以调整分片 key 的字段,但依然建议不要轻易调整 key 的值或 key 的字段构成 ,而是建议在初始化分片 key 的时候就评估好。

  • 分片集合不允许创建普通(不含分片 key 前缀)唯一性索引

1.7 多文档事务限制(>= 4.0)

  • 不支持系统库(config、local、admin)里的集合
  • 事务不支持元数据操作的修改(如 drop 集合)
  • 非增删改等操作不支持事; 事务执行周期默认最长 60 秒,超过即自动崩溃退出

最佳实践    

  • transactionLifetime,LimitSeconds 参数控制超时时间
  • 一般建议不调整或调整为更小,加快资源的释放
  • 默认事务申请锁等待时间 5 ms 如果超时即崩溃退出

1.8 其他限制

  • 全集合扫描排序的内存限制 32 MB [否则报错]

为排序添加索引;控制排序数据量

  • Aggregation 管道操作的内存限制 100 MB

控制计算数据量

调整 allowDiskUse 允许磁盘排序

  • bulkWrite 操作每批最大操作数限制 1000 或 10 w (>= 3.6)

通常建议实际业务每次批量控制在 1000 ~ 5000

默认情况下 bulkWrite 操作有序一般建议设置 false

为避免批量操作导致复制延迟可每批适当 sleep

其他建议

  • 查询、更新与删除必须带条件并且条件字段具有合适的索引
  • Update 必须使用 $set 否则会重置文档
  • Find 和 aggregate 操作,建议按需返回对应的字段
  • 数组元素添加尽量使用 $push 并且避免对中间元素进行更新
  • 超高并发写入场景 4.0 版本之前尽量避免读写分离(存在全局复制锁阻塞业务读从库)

你可能感兴趣的:(mongodb,数据库,mongodb,数据库,nosql)