mongo3.0学习笔记

来源:互联网 发布:方维借贷源码 编辑:程序博客网 时间:2024/06/08 01:20

Data Models

  1. 原子性仅保证在文档级别,对单个文档的操作是原子操作

  2. GridFS:解决BSON文档16M大小限制, GridFS用fs.files 集合存储元数据,记录chunk与文件映射关系,用fs.chunks集合记录文件片段,fs.chunks有{ files_id: 1, n: 1 }复合唯一索引,记录属于哪个文件第几个片段

  3. Keyword Search:比如字段topics : [ "whaling" , "allegory" , "revenge"]是一个列表,对其建一个multi-key index,createIndex( { topics: 1 } ),则可以快速检索

Administration

  • Capped Collections:固定大小,先进先被覆盖,多用于日志,或小量数据。缺陷:1.如果update其中某个文档,不能体积(占用空间)变大,否则失败2.不能删除,只能追加直到覆盖3.不能对固定大小集合分片

  • TTL collection(同redis过期key):TTL索引只能单字段,不支持联合索引以及列表等多值索引。

  • Locking Performance:主要关注locks.deadlockCount死锁数,globalLock.currentQueue.total排队等候锁数

  • Memory Use:mem.resident内存使用量,如果超过物理内存,将使用磁盘。mem.mapped是mongod进程内存使用量,如果大于物理内存,必有page fault(磁盘开销大)

  • Database Profiling:三个级别:0无记录,1记录慢查询,2记录所有日志。slowOpThresholdMs设置慢查询阀值,db.setProfilingLevel(0,20)参数0是级别,20是阀值。查看慢查询日志db.system.profile.find().limit(10).sort( { ts : -1 } ).pretty()

  • explain:同MySQL的explain,cursor.explain()返回执行计划,从而得知索引使用情况。

  • 查询优化:类似关系型和数据库,1建合适索引提高检索效率2.limit返回结果的记录数3.Projections 只返回必须的字段4. hint() 强制使用某个索引5.inc计数加减比客户端计算加减结果update要高效5.指定timeout:db.collection.find( { 条件} ).maxTimeMS(30)

  • 备份恢复:1文件系统快照2.自带工具dump,restore,import,export

CRUD

  1. 查询仅在一个集合内进行,结果默认无序,除非显式sort()

  2. update默认只更新符合条件的第一个,multi=true更新所有符合条件的。默认没有符合条件的不更新,upsert=true,没有则insert

  3. remove删除所有满足条件的文档

  4. Write Concern

    • Unacknowledged({w:0}):mongod不保证写入成功,客户端也不在乎

    • Acknowledged({w:1}):mongod成功将写操作写入内存,客户端能感知写入内存的成败

    • Journaled({w:1, J:true}):mongod不仅将写操作应用于内存,还写入journal(磁盘日志),断电可恢复。客户端能感知写入内存以及磁盘的成败

    • 对于replica set,默认只确认写操作在primary的结果,可以指定为至少写操作传递给几个slave(防止primary挂slave未及时同步),{ w: 3, wtimeout: 5000 }表示至少2个slave同步了该写操作或者超时5秒

  5. isolated

    类似redis事务muilt,isolated 可以保证多个文档被连续修改,不被其他操作穿插,但是遇到错误不回滚。要么全部成功,要么出错退出,出错之前的修改保留。缺陷:不支持shard

  6. Bulk 批量写入:无序速度快,后一条插入不必等待前一条成功;有序必须一条一条成功往下执行,慢

    var bulk = db.items.initializeUnorderedBulkOp();var bulk = db.items.initializeUnorderedBulkOp();bulk.insert( { _id: 1, item: "abc123", status: "A", soldQty: 5000 } );bulk.insert( { _id: 2, item: "abc456", status: "A", soldQty: 150 } );bulk.insert( { _id: 3, item: "abc789", status: "P", soldQty: 0 } );bulk.execute( { w: "majority", wtimeout: 5000 } );
  7. WiredTiger 存储引擎

    文档级别细粒度锁,journal操作日志,zlib压缩减少磁盘消耗

  8. tailable cursors

    默认迭代到末尾,游标关闭;tailable cursors迭代到末尾,阻塞,直到新的文档被insert后移到新插入的文档上。类似 tail -f

    tailable cursors不使用索引,效率不高;对于有索引集合db.collection.find( { indexedField: { $gt: <lastvalue> } } )获取最新文档,lastvalue表示最后迭代出的索引字段值

Aggregation

  1. Early Filtering(尽早过滤)

    $match, $limit, and $skip尽早减少进入流程的数据量,project投影减少不必要的字段

  2. 先match后sort减少sort工作量

  3. 先limit后skip.例如{ $skip: 10 },{ $limit: 5 }会被自动优化成{ $limit: 15 },{ $skip: 10 }尽早确定limit

  4. 合并优化:sort紧接着limit,那么limit将被合并到sort步骤一次完成(取top K)。limit紧接着limit,简单合并(取小者),一次到位。连续skip合并{ $skip: 5 },{ $skip: 2 }合并成{ $skip: 7 }。连续match做逻辑&运算一次match完毕。

  5. 缺陷:返回结果不能超过一个文档大小限制16M,此缺陷可以通过返回一个结果集的游标避免。整个pipeline各个阶段内存使用不得超过100M,此缺陷可以设置allowDiskUse避免

index

  1. Single Field Indexes

    shard cluster中如果shard key不是 id,务必确保id唯一性,否则出错

  2. Compound Indexes

    前缀规则:mongo只能使用复合索引的前缀或者整个符合索引。例如有复合索引{"a":1, "b":1, "c":1},前缀有a和a,b两个,查询a=1,查询a=1, b=1,查询a=1, b=1,c=1都能使用索引,查询a=1,c=1则只能使用a的索引

  3. Multikey Indexes

    复合索引中最多只能一个字段是多值字段(如数组)。多值索引不能当作shard key。哈希索引不能是多值字段。

    集合中有如下文档:

    { _id: 1, item: "ABC", ratings: [ 2, 9 ] },

    { _id: 2, item: "XYZ", ratings: [ 4, 3 ] }

    find( { ratings : { $elemMatch: { $gt: 3, $lt: 6 } } } )表示ratings字段至少有一个值同时满足大于3,小于6,那么不仅能使用ratings字段的索引,而且还能使用该索引的交集,两个条件单独看(-inf,6)和(3,inf),直接计算索引交集(3,6)再筛选文档

    find( { ratings : { $gte: 3, $lte: 6 } } )表示ratings字段至少有一个值要么大于3,要么小于6,那么只能普通使用该索引,不能使用索引交集

  4. Text Indexes

    文本索引字段可以使字符串或者字符串数组。db.collection.createIndex( { field: "text" } )创建索引。一个集合最多只能有一个文本索引(可以一次索引多个字段,可以复合文本索引,但只能与简单类型组成复合索引)。weights属性用来给复合文本索引指定每个字段的权值。db.collection.createIndex( { "$**": "text" } )用来创建全文索引,所有字段的字符串值都会被索引到。使用$text才能使用文本索引。使用$text查询器时不能使用hint(.文本索引不支持排序。文本索引的时空成本都很高。

  5. TTL Indexs

    TTL索引是特殊single-field索引,用来过期后删除过期key,仅适用于date类型或date数组,且不能是_id字段.例如db.collection.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )指定expireAfterSeconds即可创建TTL索引。

    如果索引字段是date数组,以日期最早的为准,即尽早过期策略。如果字段类型不符合要求,则永不过期。如果该文档缺失该索引字段,也永不过期。一个后台线程60秒为周期,周期性扫描过期文档并删除。对于副本集,扫描线程只工作在primary节点。

    capped collection不支持TTL索引,因为capped collection不支持删除。TTL索引不得与其他索引共同建立在一个字段上。

  6. Sparse Indexes

    如果某文档改索引字段缺失,普通索引当作null处理,稀疏索引直接忽略此文档。

    默认情况下,索引建立时,整个数据库被阻塞,不可读不可写。如果创建索引时指定{background: true},则不会阻塞数据库,但不能做数据库管理操作,比如删除集合。

  7. Index Intersection

    两个独立字段的索引(或者索引前缀)可以直接计算交集后迅速筛选文档。如{a:1}{b:1}两个索引对于查询find( { a: "aa", b: { $gt: 1 } } )就会使用索引交集,explain()中可以看到ANDSORTED或者ANDHASH阶段。

    索引交集和联合索引的比较:如果有联合索引{a:1, b:1}则查询find({b:1})或者sort(b:-1)时联合索引无效,因为不满足前缀规则。但这个时候两个单独索引a,b就能被使用到。

    索引交集和排序:必须find使用的索引字段和sort使用的索引字段有交集,才能用到索引交集。比如find({a:1}).sort({b:1})就无法用到ab的单独索引的索引交集,因为两个操作针对的字段毫无关联。

    对于内嵌文档的联合索引,比如文档

    {_id: 1,item: "ABC",ratings: [ { score: { q1: 2, q2: 5 } }, { score: { q1: 8, q2: 4 } } ]}

    创建索引createIndex( { "ratings.score.q1": 1, "ratings.score.q2": 1 } ),由于二者共享field path:ratings.score,所以查询时ratings.score必须在$elemMatch上才能用上索引边界的交集。

    find( { ratings: { $elemMatch: { 'score.q1': 2, 'score.q2': 8 } } } )
    不对
    find( { 'ratings.score': { $elemMatch: { 'q1': 2, 'q2': 8 } } } )
    对,$elemMatch作用在共享path:ratings.score上
  8. Replica Set建索引

    逐个停止secondary, 以standalone模式启动,建索引,再停止,再以secondary身份启动,连接到副本集,更新到与primary同步。

    前提是:oplog足够大,等secondary建完索引还能追上primary

    对于主节点,要么后台建索引,要么rs.stepDown()促使主节点变为从节点,副本集重新选举主节点,然后对于该旧的主节点(现在变为从节点)采取上面相同办法

            提示:mongo2.6+从节点也可以后台建索引,所以无论主从全部后台建索引,如createIndex( { a: 1 }, { background: true } )

      db.collection.totalIndexSize()确保索引不超过内存大小。

replica set

  • 3种角色:主,从,仲裁.仲裁节点不保留数据,仅仅参与选举,防止选举僵持。

    从节点可以指定priority 0,仅仅保留数据,不会被选举成主节点。

    hidden从节点:必须priority 0,特性:不会对client可见,hidden从节点保留数据,不会被选举成主节点,但是可能参与对其他的节点的投票。

    延迟从节点:必须priority 0,必须 hidden,参与对其他节点的投票。用于防止主节点人工误操作(删除数据),从节点立即同步,导致副本集数据丢失。

  • 部署策略

    确保投票节点数目为奇数,如果是偶数,加入仲裁借点。

    物理分布上避免两个数据中心拥有相等数目的节点,选取节点数目多的为主数据中心

    最多50节点,7个投票节点,其他非投票节点vates:0

    避免回滚:主节点接收写操作后,宕机,从节点未及时同步该写操作。接着选举出新的主节点后,原先主节点变为从节点,此时,原先的主节点就将该写操作回滚,放在数据目录的rollback目录下。可以设置write concern为majority

    read preferences:写只能在主节点,读默认为主节点,可以设置"primaryPreferred", "secondary", "secondaryPreferred", "nearest"等。如果在从节点读取数据,可能读到脏数据。比如:一次写操作,还未扩散到majority,但已经有个别小部分从节点已经同步了写操作,那么在这些从节点就能读到尚未持久化的数据。

  • read preference实现

    1.采集个节点信息 2.如果指定tag,按tag过滤 3.选择最近的节点 4.选择距离最近节点一些不太远的节点(ping响应在指定时间内) 5.在这些节点中随机挑选

    2.请求记忆:会尽量选择上一次用过的节点,除非发现该节点IOException,或者该请求线程死亡,或者read preference/primary发生变化

  • 同步

    1.initial sync: Clones all databases and build _id index, then apply change to data set, using oplog, last build all other index

  • 调整replica-set

    cfg = rs.conf()cfg.members[0].priority = 0   不能成为primarycfg.members[0].hidden = true   +隐藏cfg.members[0].slaveDelay = 3600  +延迟cfg.members[1].priority = 2rs.reconfig(cfg)
  • 状态检查rs.status()

    连接到primary节点,rs.printSlaveReplicationInfo()获取每个second同步延迟

    连接到任一成员,rs.printReplicationInfo()获取oplog大小

  • local数据库不会被同步

    local.startup_log(capped collection):每次启动插入一条日志

    local.system.replset:存放replca-set配置

    local.oplog.rs(capped collection):replica-set操作日志

Sharding

  1. 基本介绍

    shards是普通mongod进程,存储数据; Routers是mongos进程,负责请求转发与结果收集;Config Server是mongod进程,存储分片信息。每个数据库有个primary shard,存储那些没有分片的集合。sh.status()查看分片集信息。

    Balancing:balancer后台进程不停迁移数据块,使每个shard节点数据量尽量均衡

  2. 分片keys

    shard keys一旦使用,不可更改。shard keys不可以是 multikey index,不可以是text index,不可以超过512字节

    keys应该足够离散化,易于划分,

  3. Chunk Migration(数据迁移)balancer发送moveChunk命令给source shard

    source shard执行内部的moveChunk命令,执行期间,继续负责此chunk的读写

    destination shard建立索引,并且开始拷贝该chunk的数据,拷贝结束后,启动一个同步进程,去同步复制期间内,source shard产生的changes

    完全同步后,destination shard负责更新config server,更新此chunk的信息

    source shard等到同步结束以及没有游标指向该chunk后,删除该chunk

  4. 管理

    设置balancer活动的时间:

    db.settings.update({ _id: "balancer" },{ $set: { activeWindow : { start: "23:00", stop: "6:00" } } },{ upsert: true })
    其他时间不会因为balancer影响性能

    修改Chunk Size:连接mongos,use config;db.settings.save( { _id:"chunksize", value: } );

    强制某个字段unique:1.当作shard key 2.用额外一个集合保持其唯一性3.使用uuid等自身唯一的机制

0 0