• 十个 MongoDB 使用要点


     
    从 mongodb 阶段性技术总结 中抽取并整理了对大家有帮助的十个要点:
     
    1.mongodb 表名和字段名统一用小写字母
    mongodb 是默认区分大小写的,为了避免以前在 mysql 下遇到的大小写敏感导致程序访问频频出错,
    建立规范,mongodb 的表名和字段名都用小写字母命名。
     
    2.尽可能的缩短字段名的长度
    mongodb 的 schema free 导致了每笔数据都要存储它的 key 以及属性,这导致了这些数据的大量冗余。
    开发人员也许考虑到,从易读性出发设计的 key 名,基本都是按照字面意思去设计的,这导致 key 很长,对应的数据存储占用了很大的空间。
    所以,在你的程序里维护一套字典即可,尽可能降低 key 的长度。
    譬如:
    static final String CONTENT = "content";
    static final String CONTENT_TYPE = "ctype";
    static final String CONTENT_LENGTH = "clen";
     
    3.记住,mongodb 的查询每次只能用到一个索引
    对于较复杂的表结构,可能会导致你频频使用联合索引。
    但记住:
    1)mongodb 单表最大索引数为 64 。
    2)索引越多,插入或修改记录就会导致 mongodb 越慢。写锁会阻塞读请求,写得越慢,阻塞读请求越多、阻塞时间越长。
    所以,索引越加越多的时候,你可能需要审视一下表结构设计的合理性
     
    4.客户端连接数大小的设置
    mongodb-java-driver 的连接池,目前从观察到的情况是应用一开启便根据 connectionsPerHost 变量的设置,建立全部连接,然后提供给程序使用,并且一旦其中某个连接到数据库的访问失败,则会清空整个连接池到这台数据库的连接,并重新建立连接。
    而 mongodb 对中断连接的垃圾清理工作则是懒惰的被动清理方式,如果驱动程序端配置的连接数过大,一旦发生重连,则会导致 mongo 服务器端堆积大量的垃圾连接以及对应数据,导致主机资源耗尽。
    建议: mongodb 驱动的连接池大小的设置一般应该控制 100 左右。
     
    5.实例分离
    mongodb 对数据库的访问全部加锁。
    如是查询请求则设置共享锁。
    数据修改请求则设置全局排他锁,且是实例级别的排他锁。
    写锁会阻塞读请求,如果长时间持有写锁,会阻塞整个实例的读请求。
    建议:
    1)不同应用不应该共用同一个实例,防止互相阻塞
    2)如服务器资源不足,共用同一个实例,要保证读写特性相同,如都是读多写少,防止一台写多应用阻塞读请求。
    (评语:旧版本的MongoDB (pre 2.0)拥有一个全局的写入锁,这个问题在2.0版本中的得到了显著的改善,并且在当前2.2版本中得到了进一步的加强。MongoDB 2.2使用数据库级别的锁在这个问题上迈进了一大步。所以用 MongoDB 2.2的人可以忽略此条目。
     
    6.需要重点关注的 mongodb 性能指标
    关注主要性能指标:
    1)Faults:显示 mongodb 每秒页面故障的数量,这个是 mongodb 映射到虚拟地址空间,而不是物理内存。这个值如果飙高的话,可能意味着机器没有足够的内存来存储数据和索引。
    2)Flushes:每秒做了多少次 fsync,显示多少次数据被刷新进了磁盘。
    3)locked:写锁。
    4)idx miss:索引未命中比例。
    5)qr | qw:读写锁的请求队列长度。
    6)conn: 当前已经建立的连接数。
     
    7.严重的空间碎片问题
    mongodb 如果数据修改很频繁,会出现比较严重的空间碎片问题,表现在磁盘文件扩张与实际数据量不相符,内存不够用,索引命中率低,查询效率降低。
    碎片整理,目前我们采用的版本没有太有效的方法。
    可以用 db.repaireDatabase() 来整理数据库,这个过程非常的慢。
    如果是 master/slave 模式,则相当于执行一次主从切换,然后从新建立从库。
    如果是 replSet 架构,可以停掉数据库,然后删除数据目录,从新从复制组中全同步数据,这个时候要考虑 oplog 的尺寸。
    一个大体的步骤:
    1)先调用rs.freeze(1200),将每个不想让它成为 primary 的机器让它在 1200 秒内无法成为 primary(这步也可以不做);
    2)将 primary stepDown,不出意外新的 primary 会起来;
    3)将原 primary kill 掉;
    4)删掉所有 data 数据(调用 repair 很慢,真不如干掉重新来);
    5)再重启动原 primary 的进程;
    6)以此循环完成整个复制组的全部重建。
     
    8.连接池 WriterConcern 模式选择
    有些应用配置了 WriterConcern.FSYNC_SAFE 模式;这种配置意味着客户端在插入数据或更新数据的时候,要求 mongodb 必须将所更新的数据写入磁盘并返回更新成功的信息给程序。
    如果碰上应用程序访问压力大,mongodb 就会反应迟钝,并可能会假死。
    针对此情况,需要评估数据的一致性需求,做出合适调整。
    我们一般建议关闭此选项。
    (评语:刘奎波的业务中心优化时就关闭了这个 WriterConcern.FSYNC_SAFE 模式)
     
    9.开发时注意的细节
    1)更新某条数据的时候,先查出来再更新会减小锁的时间
    2)只有真正需要的字段才select出来;
    3)只有返回很少结果的查询才用索引,否则会加载太多数据,比没有用索引还慢
    4)属性比较多的时候,建立分层的关系能够提高查询效率,否则每个记录都要过一遍才能找到要的属性。(评语:貌似说的是以 Array 形式存储的 subdocument)
    5)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);

     
    10.关于硬件资源的选择
    虚拟机可以很好的隔离资源,并可动态的扩展。
    我们建议 mongodb 的部署采用虚拟机的方式,每个虚拟机部署一个实例,使各节点分散在不同的物理机上,根据应用的前期预测,平衡虚拟机的之间的i/o。
     
    参考资源:
    1)horizonhyg,2012,Mongodb写入安全机制--GetLastError
    2)horizonhyg,2012,java连接mongo

    赠图2枚:
    http://ww2.sinaimg.cn/bmiddle/5ec7ae37jw1e152gwvn4qj.jpg
     
    http://ww3.sinaimg.cn/bmiddle/4889c95fjw1e14sp72swrj.jpg
  • 相关阅读:
    hdu 4027 Can you answer these queries? 线段树
    ZOJ1610 Count the Colors 线段树
    poj 2528 Mayor's posters 离散化 线段树
    hdu 1599 find the mincost route floyd求最小环
    POJ 2686 Traveling by Stagecoach 状压DP
    POJ 1990 MooFest 树状数组
    POJ 2955 Brackets 区间DP
    lightoj 1422 Halloween Costumes 区间DP
    模板 有源汇上下界最小流 loj117
    模板 有源汇上下界最大流 loj116
  • 原文地址:https://www.cnblogs.com/duanweishi/p/5037926.html
Copyright © 2020-2023  润新知