一.命名规则

1.数据库命名规则

数据库名可以是满足以下条件的任意UTF-8字符串:
(1)不能是空字符串(”") ;
(2)不能含有”(空格)、.、$、/、、和(空字符);
(3)应全部小写;

(4)最多30字符。
注意事项: 数据库名最终会变成文件系统里面的文件,这也就是有如此多限制的原因。把数据库的名字放到集合名前面,得到就是集合的完全限定名,称为命名空间。例如:如果你在cms数据库中使用blog.posts集合,那么这个集合的命名空间就是cms.blog.posts。 命名空间的长度不得超过121字节,在实际使用当中应该小于100字节。

2.集合命名规则

必须满足下列条件的任意UTF-8字符串
(1)集合名不能是空字符串“”;
(2)集合名不能含有字符(空字符NULL),这个字符表示集合名的结尾;
(3)集合名不能以“system.”开头,这是为系统集合保留的前缀。例如system.users这个集合保存着数据库的用户信息,system.namespaces集合保存着所有数据库集合的信息;
(4)用户创建的集合名字不能含有保留字符$。除非你要访问系统创建的集合,否则不可在名字里出现$;
(5)首字母必须大写,组合词每个词首字母必须大写,例如NoticeQueue、UserBase、UserExpand。

3.文档的键命名规范

(1)键不能含有(空字符)。这个字符用来表示键的结尾;
(2)和$有特殊的意义,只有在特定环境下才能使用。通常来说就是被保留了,使用不当的话,驱动程序会提示;
(3)以下划线“_”开头的键是系统保留的,不可以“_”开头命名键名称;
(4)键名建议遵循英文简写、如因意义相近可以通过下划线加上全称的方式进行区别,但应遵循键名不超过35个字符例 如,id、state、title、content、mail_name、subtitle database_admin database_administrator;
(5)键引用必须采用集合名+被引用键名称。例如集合User的键id在集合UserInfo中被引用,必须用user_id作为键名; 一个集合中存在多次引用相同集合某一个键,则命名按照业务标识+集合名+被引用键名称。例如Message集合,发送者键名称:from_user_id 收信人键名称:to_User_id或者to_user_id (根据该业务实际情况调整,但只能统一一种规则);
(6)只有在遇到引用情况下,键中包含的集合名首字母需要大写,其他一律小写格式。

二.优化

1.库集合优化

(1)在创建新的库前应尽量评估该库的体积、QPS等,提前与DBA讨论是应该新建一个库还是专门为该库创建一个新的集群;

(2)如果评估单集合数据量较大,可以将一个大表拆分为多个小表,然后将每一个小表存放在独立的库中或者sharding分表;
(3)特定场景下使用Capped Collection或TTL Indexes,以自动处理失效数据
(4)创建集合规则不同的业务场景是可以配置进行不同的配置:
a. 如果是读多写少的表在创建时我们可以尽量将page size设置的比较小,比如 16KB,如果表数据量不太大("internal_page_max=16KB,leaf_page_max=16KB,leaf_value_max=8KB,os_cache_max=1GB")
b. 如果这个读多写少的表数据量比较大,可以为其设置一个压缩算法,例如: "block_compressor=zlib,internal_page_max=16KB,leaf_page_max=16KB,leaf_value_max=8KB"
c. 注意:该zlib压缩算法不要使用,对cpu消耗特别大,如果使用snapp消耗20% cpu,而且使用zlib能消耗90%cpu,甚至100%
d. 如果是写多读少的表,可以将 leaf_page_max设置到1MB,并开启压缩算法,也可以为其制定操作系统层面page cache大小的os_cache_max 值,让它不会占用太多的page cache内存,防止影响读操作
e. 案例 db.createCollection( "logs", { storageEngine: { wiredTiger: {configString: "internal_page_max=16KB,leaf_page_max=16KB,leaf_value_max=8KB,os_cache_max=1GB" } } } ) 说明: 读多写少的表 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 默认为64MB

2.文档优化

(1)尽量将同样类型的文档存放在一个集合中,将不同类型的文档分散在不同的集合中;相同类型的文档能够大幅度提高索引利用率,如果文档混杂存放则可能会出现查询经常需要全表扫描的情况
(2)禁止使用_id,如:向_id中写入自定义内容,MongoDB的表与InnoDB相似,都是索引组织表,数据内容跟在主键后,而_id是MongoDB中的默认主键,一旦_id的值为非自增,当数据量达到一定程度之后,每一次写入都可能导致主键的二叉树大幅度调整,这将是一个代价极大的写入, 所以写入就会随着数据量的增大而下降,所以一定不要在_id中写入自定义的内容
(3)尽量不要让数组字段成为查询条件,如果为一个数组字段添加索引,那么MongoDB会主动为这个数组中的所有元素依次添加独立索引,例如: 为数组字段{a:[x,y,z]}添加索引{a:1},实际上添加的索引为:{a:[x:1]}、{a:[y:1]}、{a:[z:1]} 如果一个组合索引中存在两个数组字段,那么索引的数量将是两个数组字段中元素的笛卡儿积,所以MongoDB不允许索引中存在一个以上的数组字段
(4)不要存放太长的字符串,如果这个字段为查询条件,那么确保该字段的值不超过1KB,如果字段较大,应尽量压缩存放,如果字段较大且会成为查询条件,例如一长串的url,尽量转成md5后存放,
(5)由于MongoDB是大小写敏感的,如果字段无需大小写敏感,为了提高查询效率应尽量存放统一了大小写后的数据,如:全部小写或为该字段增加一个统一了大小写的辅助字段
(6)分片键必须有索引,分片键大小限制为512byte,一旦集合已经分片,不可以直接修改分片键。不接受向已进行分片的collection上插入无分片键的文档,也不支持空值插入
(7)片键的设计原则:
a. 所有的插入、更新、删除将会均匀发送到集群的所有分片中。
b. 所有的查询将会在集群中的所有分片中均匀地分发。
c. 所有的更新或者删除操作将会只面向相关的分片,不会发送到一个没有存储被修改数据的分片上。
d. 一个查询将不会被发送到没有存储被查询数据的分片上
(8)如若将日期类型选择为string,不同的日期格式的文档,不支持等值查询,不支持范围查询 解读:创建一个测试集合product,分别向集合插入Date:"20180425"和Date:"2018-04-25"两笔数据。等值查询、范围查询($gte, $lte)只能查到日期格式相同的数据,都为一笔数据
(9)通过$size查询数组大小,但是$size运算符不使用索引和限制准确匹配(不能指定$Sized 范围)。因此,如果需要基于数组的大小执行查询,可以在文档设计中增加size属性。 解读:例如在商品评价中,其他人可以对评价进行投票。为了阻止用户多次投票和对有帮助的评论进行排序,所以,评价文档设计是:在一个数组字段(voter_ids)保存了所有评论用户的ID,而数组大小缓存在helpful_votes字段里

3.索引

(1)MongoDB的索引仅支持1K以内的字段,如果你存入的数据长度超过1K,那么它将无法被索引
(2)MongoDB 的组合索引使用策略与 MySQL 一致,遵循"最左原则",优先使用覆盖索引,即Covered Query,复合索引字段顺序(较精确匹配字段、排序字段、范围查询字段)
(3)索引名称长度不要超过128字符
(4)索引数量<=2,应尽量综合评估查询场景,通过评估尽可能的将单列索引并入组合索引以降低所以数量,结合2,3点
(5)在数据量较大的时候,MongoDB 索引的创建是一个缓慢的过程,所以应当在上前线或数据量变得很大前尽量评估,按需创建会用到的索引
(6)MongoDB 支持 TTL 索引,该索引能够按你的需要自动删除XXX秒之前的数据并会尽量选择在业务低峰期执行删除操作;看业务是否需要这一类型索引
(7)如果你存放的数据是地理位置信息,比如:经纬度数据。那么可以在该字段上添加 MongoDB 支持的地理索引:2d 及2dsphere,但他们是不同的,混用会导致结果不准确; 2d:只能用于点对点索引,适用于平面地图和时间连续的数据,比如非常适用于游戏地图【2dsphere:允许指定点、线和多边形。适用于地球表面类型的地图(球体) 】如果在球体表面创建2d索引,则会导致极点附近出现大量扭曲变形,最终导致结果不准确
(8)MongoDB 的全文索引目前仍然处于“实验”阶段,性能并不够理想,当前不建议使用
(9)MongoDB2.4开始,支持索引的 ICP 功能,可以通过其合理减少索引数量,从 MongoDB2.4开始,组合索引能够被更有效的利用

4.查询操作优化

(1)在查询条件的键上,或者排序条件的键上必须创建索引;
(2)使用limit限定返回结果条数,最多不能超过100;
(3)skip+limit翻页,越往后面越慢。比较靠谱的做法是,先找出上次的id,翻页的时候不用skip: last_row_id = ObjectId('....'); db.activity_stream-<find({_id:{$lt:last_row_id },User_id:20 } ).sort( {_id:-1} ).limit(10);
(4)只查询使用到的字段,而不查询所有字段;
(5)对于Circular Fixed Size Collections合理使用;apped Collections比普通Collections的读写效率高
(6)索引中的-1和1是不一样的,一个是逆序,一个是正序,应当根据自己的业务场景建立适合的索引排序
(7)在开发业务的时候尽量检查自己的程序性能,可以使用explain() 函数检查你的查询执行详情,另外 hint() 函数相当于 MySQL 中的force index()
(8)查询中的某些$操作符可能会导致性能低下,如 $ne,$not,$exists,$nin,$or,尽量在业务中不要使用 a. $exist:因为松散的文档结构导致查询必须遍历每一个文档 b. $ne:如果当取反的值为大多数,则会扫描整个索引 c. $not:可能会导致查询优化器不知道应当使用哪个索引,所以会经常退化为全表扫描 d. $nin:全表扫描 e. $or:有多少个条件就会查询多少次,最后合并结果集,所以尽可能的使用 $in
(9)如果你结合体积大小/文档数固定,那么建议创建 capped(封顶)集合,这种集合的写入性能非常高并无需专门清理老旧数据,需要注意的是 capped 表不支持r emove() 和update()
(10)在写入数据的时候,如果你需要实现类似 MySQL 中INSERT INTO ON DUPLICATE KEY UPDATE 的功能,那么可以选择 upsert() 函数: db.analytice.update( {"url":"/blog"}, {"$inc":{"visits":1}}, true ) (11)不要一次取出太多的数据进行排序,MongoDB 目前支持对32MB以内的结果集进行排序,如果需要排序,那么请尽量限制结果集中的数据量
(12)MongoDB 的聚合框架非常好用,能够通过简单的语法实现复杂的统计查询,并且性能也不错,聚合框架是MongoDB的高级查询语言,它允许通过转换和合并由多个文档中的数据来生成新的单个文档里不存在的文档信息。可以把MongoDB的聚合框架等价于SQL的Group By语句,在聚合框架中,$project操作符允许过滤传递给管道下一个阶段的字段。限制每个文档传递的大小,可以改善性能,尤其是在处理大文档且只需要每个文档一部分数据的场景下
(13)如果需要清理掉一个集合中的所有数据,那么remove()的性能是非常低下的,该场景下应当使用drop(),remove()是逐行操作,所以在删除大量数据的时候性能很差
(14)写入大量数据的时候可以选择使用batchInsert,但目前MongoDB每一次能够接受的最大消息长度为48MB,如果超出48MB,将会被自动拆分为多个48MB的消息
(15)在使用数组字段做为查询条件的时候,将于覆盖索引无缘,这是因为数组是保存在索引中的,即便将数组字段从需要返回的字段中剔除,这样的索引仍然无法覆盖查询
(16)在查询中如果有范围条件,那么尽量和定值条件放在一起进行过滤,并在创建索引的时候将定值查询字段放在范围查询字段前
(17)更新操作:
a.先查询后更新,通过主键key更新,提高更新效率,
b.多文档更新,在默认情况下,只会更新匹配查询器的第一个文档。要更新所有的匹配文档,需要显式指定多文档更新模式--添加参数multi:true
c.在文档级别更新是原子性的,这意味着一条更新10个文档的语句可能在更新3个文档后由于某些原因失败,应用程序必须根据自己的策略来处理这些失败
d. update结合upsert可以用来处理,当文档存在时更新,文档不存在时插入。如果查询选择器匹配,更新就正常执行;如果没有匹配的文档,就会插入新的文档。新文档的字段是查询选择器和目标更新文档的逻辑合并

5.连接规范

(1)正确连接副本集,副本集提供了数据的保护、高可用和灾难恢复的机制。如果主节点宕机,其中一个从节点会自动提升为从节点。
(2)合理控制连接池的大小,限制连接数资源,可通过Connection String URL中的maxPoolSize 参数来配置连接池大小。
(3)复制集读选项 默认情况下,复制集的所有读请求都发到Primary,Driver可通过设置的Read Preference 来将读请求路由到其他的节点。
a. Primary:默认规则,所有读请求发到Primary。
b. PrimaryPreferred: Primary优先,如果Primary不可达,请求Secondary。
c. Secondary:所有的读请求都发到Secondary。
d. SecondaryPreferred:Secondary优先,当所有的Secondary不可达时,请求Primary。
e. Nearest:读请求发送到最近的可达节点上(通过ping探测得出最近的节点)

mongodb 开发规范的更多相关文章

  1. mongoDB开发规范

    mongoDB库的设计 mongodb数据库命名规范:db_xxxx 禁止使用任何 " _ "(下划线)外的特殊字符 禁止使用数字打头的库名 数据库名最多为 64字符 mongoD ...

  2. MongoDB 数据库开发规范

    MongoDB 数据库开发规范 转载自-落雨_ https://developer.aliyun.com/article/255536 简介: mongoDB库的设计 mongodb数据库命名规范:d ...

  3. MySQL架构设计谈:从开发规范、选型、拆分到减压(转)

    作者介绍 李辉,原新浪爱彩票运维负责人,常用网名:门牙没了.曾主导新浪爱彩票的MySQL运维工作.培训合伙人.资深讲师,中国科学院大学在读研究生(大数据方向),擅长大型项目的关系型数据库运维和管理,现 ...

  4. 我的公司培训讲义(1):.NET开发规范教程

    这是1年多以前我在公司所做讲座的讲义,现在与园友们分享,欢迎拿去使用.一起讨论.文中有若干思考题,对园友们是小菜一碟.另有设计模式讲义一篇,随后发布.博文上了首页,感谢博客园团队推荐,也感谢所有园友的 ...

  5. 转载:移动web开发规范

    本文来源:http://blog.csdn.net/joueu/article/details/44329825 以下是规范建议,均是日常在开发当中的的一些经验,仅供参考. 移动web开发规范 一.头 ...

  6. php与数据库代码开发规范

    php与数据库代码开发规范 1/25/2016 6:00:31 PM php对各类变量命名规范 目录名 文件命名 局部变量命名 使用英文动词名词,用下划线作为单词的分割,所有字母均使用小写 目录 up ...

  7. 【敏捷开发】Android团队开发规范

    这里说的开发规范分成目录规范,项目和包名的命名规范,类,方法,变量和常量的命名规范这几种. 目录规范 目录规范——在开发中整体文件夹组织结构. Requirement——需求文档文件夹 Design— ...

  8. 从零开始编写自己的C#框架(3)——开发规范

    由于是业余时间编写,而且为了保证质量,对写出来的东西也会反复斟酌,所以每周只能更新两章左右,请大家谅解,也请大家耐心等待,谢谢大家的支持. 初学者应该怎样学习本系列内容呢?根据我自己的学习经验,一般直 ...

  9. 从零开始编写自己的C#框架(3)——开发规范(转)

    由于是业余时间编写,而且为了保证质量,对写出来的东西也会反复斟酌,所以每周只能更新两章左右,请大家谅解,也请大家耐心等待,谢谢大家的支持. 初学者应该怎样学习本系列内容呢?根据我自己的学习经验,一般直 ...

随机推荐

  1. DBA职责和任务

    DBA守则在对生产环境进行修改前,一定要进行备份,一定要在测试环境进行测试,否则不要进行轻易的更改一次尽量只做一件事,不要受环境影响 DBA的十大任务1.了解和掌握硬件环境2.规划数据库3.安装数据库 ...

  2. ps 指令

    ps显示系统当前进程信息, ps 存在多个版本,因此 ps options 的种类繁多.这里只列举平时开发过程中常用的命令,如果有错误或者更好的例子.烦请在评论区指出 语法 ps [options] ...

  3. nginx修改响应头(可屏蔽后端服务器的信息:IIS,PHP等)

    修改nginx反向代理请求的Header 需要使用到proxy_set_header和add_header指令.其中: proxy_set_header 来自内置模块ngx_http_proxy_mo ...

  4. Advanced REST Client 的安装

    1.解压Advanced-REST-client_v3.1.9.zip到当前文件夹,得到Advanced-REST-client_v3.1.9目录      2.在Chrome浏览器中打开:chrom ...

  5. vmware vSphere Data Protection 6.1--------2-初始化

    一.简介 安装完vdp接下来就是部署初始化了 安装篇请参考:vmware vSphere Data Protection 6.1部署 二.开始初始化 登陆https://192.168.216.200 ...

  6. 在论坛中出现的比较难的sql问题:16(取一个字段中的数字)

    原文:在论坛中出现的比较难的sql问题:16(取一个字段中的数字) 所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路. 问题:取一个字段中的数字http://bbs.csdn ...

  7. MySQL绿色版mysql-5.7.17-winx64简洁安装教程

    1.解压MySQL绿色版,复制my-default.ini,修改名称为my.ini 2. 以下为my.ini文件 # For advice on how to change settings plea ...

  8. 2..net core 和.net framework 版本

    同一台机器上可以安装多个版本的.net core runtime.比如: 每个.net core项目都可以指定自己所用的版本,所以改变某个项目的target version不会影响到其他的.安装新的r ...

  9. gradle上传jar包到maven公共仓库

    首先这里说的中央仓库 是指的 https://issues.sonatype.org/ 而不是maven私服. 其次是使用gradle上传jar包,maven上传,网上有很多教程,这里不做赘述. 首选 ...

  10. navigator(浏览器对象)Screen对象(屏幕)

    浅谈navigator对象: 注意:不是所有浏览器都支持 .cookieEnabled  判断是否启用了cookie  在客户端硬盘持久保存用户私密数据的小文件 .plugins 浏览器安装的所有插件 ...