mongoDB实战读书笔记
2021-10-15 17:37:25   150  举报             
     
         
 AI智能生成
  mongoDB in Action 要点整理
    作者其他创作
 大纲/内容
  第一章 简介
    
     特征    
     面向文档    
     BSON格式(二进制json)  
     支持Ad hoc查询的nosql
    
     即席查询    
     就是类似sql语句这种的,声明式查询,与命令式区别  
     索引    
     B树  
     LSM树    
     3.2版本可用  
     支持为字段添加二级索引,每个集合允许64个索引
  
     持久化    
     写日志文件(op log)    
     默认开启 100ms写一次
  
     存储引擎    
     WireTiger  
     扩展    
     基于范围分片    
     只在分片节点内冗余数据  
     基于hash和tag分片  
     复制    
     集合内可复制  
     自动容灾  
     工具    
     mongodump /mongosniff /mongostat /mongotop 等等  
     应用场景    
     可变的schema  
     数据集大小超过内存,会开始访问磁盘,速度变慢,mmap  
     第二章 mongo命令行
    
     CRUD    
     创建
    
     insert()    
     mongo中的库、集合在第一次插入数据时才会创建,不用手动创建  
     查询    
     find()/count()    
     条件关键字 $AND $OR $LT $GT
  
     pretty()格式化  
     更新    
     update()    
     $set指定更新内容,否则执行替换更新
  
     $unset去掉指定字段  
      $push更新集合  
     删除    
     drop()    
     删除集合  
     remove()    
     删除文档
  
     高级查询
    
     explain()    
     参数:
    
     explain(工作模式)  
     关键输出:    
     totalKyesExamined 用到的索引数
  
     totalDocsExcamined 遍历文档数
  
     executionTimeMills 执行时间
  
     索引    
     createIndex()    
     参数:{ 索引字段:索引名}
  
     getIndexes()  
     数据库命令
    
     db.stats()    
     数据库信息
  
     db.cols.stats()    
     集合信息
  
     db.currentOp()    
     监控当前操作  
     db.serverStatus()    
     集群维度的统计信息  
     connections    
     "connections" : {
"current" : <num>,
"available" : <num>,
"totalCreated" : <num>,
"active" : <num>
}
    "current" : <num>,
"available" : <num>,
"totalCreated" : <num>,
"active" : <num>
}
 命令执行原理    
     db.runCommand()    
     执行内建命令的函数  
     $cmd
    
     内建命令集合  
     命令帮助    
     db.help()  
     查看命令源码    
     输入命令 但是不加括号
eg: 输入db.cols.save查看save()源码
  
    eg: 输入db.cols.save查看save()源码
 第三章 ruby驱动
    
     mongo驱动作用    
     生成对象ID    
     时间+机器id+进程+计数器(4+3+2+3=12bytes)  
     对象和BSON格式之间转换  
     和数据库建立TCP连接  
     第四章 为业务设计mongo数据库
    
     设计schema的技巧    
     设置唯一“主键”    
     设置一个slug字段,让它做唯一索引,保存一个便于阅读理解的key    
     比如商品编号 "IPhoneUsbCharger-34212"
  
     不用ObjectId,因为ObjecID是一串无意义的字符
  
     表示关联关系    
     因为mongo不支持join连接,所以可以直接把被关联的对象的信息保存在数据文档中                                                                            (也可以按关联对象的id查询,直接保存只是减少查询次数&最好保存不经常变动的信息)  
     比如 每个子类别不仅保存一个父类别的id,还保存了父类别的名称等(用户查询需要返回的信息)
  
     这种方式 违反了数据库的第二,三范式 
    
     存在传递依赖,父类别改名时,所有子类别文档也要更新  
     不是每个属性都依赖主键
  
     设计mongo 库、表时的限制    
     数据库限制 索引和集合数不能超过26000(WiredTiger引擎不限制)
    
     创建数据库后,mongo会在/data/db目录创建一系列文件,以库名为前缀  
     xx.ns文件表示数据库xx的命名空间,固定大小16MB    
     16MB能保存不超过26000个元数据  
     可以通过修改--nssize改变限制  
     存储集合和索引的文件大小不超过2GB
    
     mongo以预分配的方式在磁盘创建文件    
     扩容过程 64mb->128mb ... -> 2gb
  
     db.stats() 输出的 fileSize表示数据库文件占用字节
  
     总索引大小最好能够被装入内存    
     db.stats() indexSize查看全部索引大小
  
     集合    
     集合名不超过128字符  
     固定集合(达到固定大小时,最先输入的记录被覆盖)    
     固定空间占用的集合(16kb等)  
     固定文档数的集合  
     TTL集合    
     用createIndex-- expireAfterSeconds创建一个管理超时时间索引
  
     索引字段比较字段的值和当前时间差,超过expireAS会删除文档(不是删除集合)  
     固定集合不支持TTL  
     文档    
     尽量使用短的字段名,因为字段名也被大量保存  
     字符串必须用utf8编码  
     单个文档大小限制为16MB  
     文档嵌套深度最大值100  
     第五章 mongo支持的查询方式
    
     查询语言
    
     比较
    
     $lt,$gt
    
     db.xx.find({'age':{'$gt':20}})  
     范围    
     $in $all $nin
  
     布尔查询
    
     $ne $not $or  $nor...
    
     db.xx.find({'$and':['xxxxxx']})  
     包含某个字段
    
     $exists
  
     数组
    
     包含某些字段 $elemMatch
  
     大小 $size
  
     自定义
    
     $where 结合js函数查询
  
     正则
    
     前缀 表达式 可以用索引,其他不行
  
     特殊查询    
     $mod 整除计算结果匹配
  
     $type 字段类型匹配
  
     $text 在文本上执行搜索
  
     查询结果过滤    
     控制返回字段,再传一个参数值为1包含,0不包含    
     只返回 id db.xx.find({'name':'xx'},{'id':1})  
     跳过 多少个记录
    
     $skip  
     返回数量
    
     $limit  
     排序
    
     $sort
  
     返回一定范围
    
     $slice
    
     {$slice:-5} 最后5个
  
     第六章 mongo的聚合查询框架
    
     定义    
     mongo中的聚合类似于SQL中的group by
  
     聚合管道    
     每一步的处理输出是下一步的输入  
     常用操作    
     $project 
    
     指定输出字段  
     $match 
    
     条件过滤  
     $group
    
     根据指定key分组  
     $unwind    
     "展开,放松" 扩展数组,把每个元素为一个文档  
     $sort  
     $out    
     输出到新集合  
     示例    
     db.products.aggregate([{$match : ... } , {$group : ...},{$sort : ...},{ $out : ....}])  
     聚合操作内支持的函数
    
     $group函数,用来改变输出集合的内容    
     $sum , $avg , $addToSet ....
  
     $group:{ _id:{user:'$user_id', list: {$push: '$name'}}
  
     字符串函数    
     $concat $substr $toLower .....
  
     算术函数
    
     $add $mod ...
  
     日期函数
  
     逻辑函数  
     集合操作符    
     处理输出的数组    
     $setUnion 合并两个集合
  
     $setIntersection 返回公共元素
  
     $setDifference 返回不同元素 
  
     ....  
     聚合的性能
    
     性能相关的选项    
     explain
    
     返回聚合操作的查询信息,索引,扫描范围等  
     allowDiskUse    
     当处理大集合时,允许访问磁盘  
     cursor    
     用返回结果的指针来代替返回整个结果,减小返回数据大小  
     优化手段    
     在管道操作中减小文档的数量 和 大小
  
     只有$match 和 $sort才能使用索引
  
     使用分片集群时,$match和$project会在单个分片执行,其他的操作符会在主要片执行    
     ????  
     map-reduce    
     需要自己编写js函数,比聚合出现早,但不再作为主要查询手段  
     第七章 mongo中的更新操作
    
     更新操作    
     方式    
     update全部替换  
     update + $set 更新指定字段
    
     网络传输的内容少  
     格式    
     db.xx.update( {查询条件},{$操作符:{更新内容},{更新选项}} )  
     选项    
     multi:true    
     批量更新,默认只会更新一个文档,不保证批量操作的原子性,需要自己处理失败
  
     upsert:true    
     文档不存在时,插入新记录,新记录会合并查询和更新指定的字段做为内容
  
     操作符    
     $inc N
    
     N也可以是负数
  
     $set
    
     设置字段值  
     $unset
    
     删除字段  
     $rename
    
     重命名字段key  
     $setOnInsert:默认值    
     和upsert同时使用,在添加时使用默认值
  
     数组操作符
    
     $push $each $sort 等等
  
     删除    
     remove全部文档    
     db.xxx.remove()  
     remove某些文档    
     db.xxx.remove({查询条件})  
     原子性操作    
     findAndModify    
     原子操作:(借助锁机制)相当于CAS操作,先查询获得结果然后更新,返回被更新的文档
  
     限制    
     一次只能更新一个文档  
     参数    
     new:true    
     是否返回更新后的文档,否则返回更新之前的
  
     sort    
     因为只能更新一个,可以用sort选择要更新的文档  
     upsert    
     如题 用upsert的方式修改
  
     fields    
     控制文档返回的字段  
     $isolated操作符
    
     db.xx.update(   {$isolated:true} ,   {$set:xxx} )
  
     使用它,表示当前操作是独立的,持有锁并阻塞其他操作
  
     限制    
     在分片集合上无法使用  
     如果操作中途失败,mongo不会回滚数据  
     锁机制
    
     WiredTiger引擎    
     支持文档级别的锁(SQL中的行锁)  
     老版本    
     数据库级别的锁  
     第八章 索引
    
     基本概念    
     用B树实现
    
     每个索引至少需要8kb空间 ???
  
     被索引的字段最大不超过1024kb  
     可以通过索引文档个数和大小估算B树的内存占用
  
     节点空间利用率为60% ??
  
     非聚集索引    
     聚集索引的索引顺序和数据在磁盘的物理顺序一致    
     innodb的主键  
     mongo中的索引不是聚集索引,索引顺序和数据顺序没有关系  
     设计索引    
     保证索引大小能保存在内存中,避免磁盘I/O
  
     索引越多,数据变化时,需要执行更新索引的操作越多  
     使用复合索引时,注意选择的字段顺序  
     索引类型    
     唯一索引    
     createIndex({unique:true})  
     保证索引字段在文档中唯一,插入重复数据会提示异常
  
     唯一索引最好在填充数据前创建,否则需要手动对字段去重  
     多键索引    
     当索引字段是数组类型时使用,数组中的值都会保存在索引里  
     哈希索引    
     createIndex({recipe_name:'hashed'})  
     一般值相似的几个索引会保存在相邻的位置,Aa Abc Abb ....
  
     哈希索引会把索引的值经过hash计算后再保存,这样索引会在集群中均匀分布(适合分片集合类型)  
     限制    
     不支持范围查询,仅支持等值查询  
     不支持多建索引  
     浮点数会被当做整数计算,4.2 和 4.3的索引相同
  
     TTL索引    
     db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )  
     适用于时间类型字段  
     过期时间是 字段值X + expireAfterSeconds 秒
  
     对嵌套的文档字段无效
  
     操作索引    
     常用命令    
     db.collection. getIndexes() / dropIndex() / createIndex()
  
     整理碎片    
     db.values.reIndex()  
     随着数据的变化,索引更新后会产生碎片  
     索引构建    
     大型数据库创建索引耗时会很长    
     处理办法    
     在后台构建索引    
     createIndex({background:true})  
     离线构建索引
    
     复制主节点,构建索引,替换  
     索引创建过程中会对数据库加锁
  
     构建执行步骤    
     对索引值做排序  
     把排序值插入索引  
     查看构建进度    
     db.currentOp()  
     索引优化
    
     profile分析器    
     配置命令
    
     db.setProfilingLevel(0/1/2,timeout) 
    
     0 禁用 1 记录慢操作 2 记录全部读写操作
  
     查询监控结果    
     db.system.profile.find()    
     结果保存在system.profile集合
  
     explain函数
    
     xx.find(xx).explain("executionStats")    
     参数指定输出内容
  
     参数    
     allPlansExecution/executionStats/queryPlaner  
     输出关注    
     nReturned    
     查询匹配和返回的文档数量  
     totalKeyExamined    
     查询扫描的文档数量,越小越好  
     mongoDB内置的查询优化器    
     选择最优索引组合成查询计划    
     生成的查询计划会被缓存一段时间  
     原则    
     避免scanAndOrder,如果要排序,优先尝试使用索引排序  
     优先使用满足所有查询字段的索引  
     第九章 文本搜索
  
     第十章 WireTiger简介
    
     可插拔的存储引擎接口    
     存储引擎    
     mongo数据库和硬件的直接接口  
     影响读写磁盘数据的方式,数据存储时的数据结构
  
     v3.0提供了引擎切换的功能,满足不同使用场景的需要  
     wiredTiger    
     特点    
     多核可伸缩 Scalable Multicore Programming    
     风险指针和无锁算法的应用  
     使用mvcc架构  
     使用B树,可以切换LSM树
    
     LSM在写入表现好,读表现差  
     文档级别的并发控制    
     多个客户端可以同时修改集合的不同文档  
     使用wiredTiger
    
     确保64位系统  
     配置    
     engineConfig    
     cacheSize    
     申请多少内存
  
     journalCompressor    
     使用哪种日志压缩器,默认snappy  
     collectionConfig    
     blockCompressor    
     集合数据压缩方式 默认snappy,可选zlib 或 none
  
     indexConfig    
     prefixCompression    
     是否压缩索引,默认true
  
     对比MMAPv1引擎    
     磁盘占用明显减少    
     mmap每次数据增长会申请2G的磁盘空间  
     性能对比    
     使用mongobenchmark执行测试脚本  
     读写性能wiredTiger优于mmapv1  
     开启压缩的wt在插入上比未开启压缩的wt慢,在读取上快,磁盘占用小
    
     如果磁盘空间充足使用不压缩的wt  
     对比RocksDB
    
     RockDB使用LSM树引擎,适用于高并发写入场景
  
     mongoDB可以使用RocksDBm引擎  
     第十一章 副本集
    
     副本集的特点
    
     节点分为 主 从 裁判(arbiterOnly) 三种,可以包含50个节点(v3.0)
    
     裁判不复制数据
  
     提高读性能    
     不能保证一致性读(只有最终一致)  
     不适用 写请求大于读请求的场景
  
     不适用于大数据集存储,需要使用分片代替  
     自动容灾  
     冗余数据    
     历史数据还是要备份快照,两者结合使用  
     副本集的命令    
     rs.initiate()    
     初始化  
     rs.reconfig()    
     重新配置,注意 配置变化会导致重新选举主节点  
     rs.add("pc.local:7000")    
     添加节点  
     rs.slaveOk()    
     开启从节点的读取,默认情况,从节点无法查询  
     db.isMaster()、rs.status()    
     副本集的节点信息
  
     db.getReplicationInfo()    
     当前节点的数据复制情况  
     rs.help()    
     副本集命令帮助
  
     工作原理    
     oplog介绍    
     保存在副本集每个节点的local数据库中    
     local数据库还保存了索引,集群选举信息等等重要数据  
     是一个固定大小的集合    
     64位系统默认大小为1G或者磁盘可用空间的5%  
     启动命令 mongod -oplogSize 设置自定义大小
  
     记录节点所有数据变化,每条记录保存了 时间戳 ,操作类型, 操作数据 等
  
     用oplog实现数据复制    
     主节点写入    
     操作记录到oplog  
     不会同步写所有从节点,通过writeConcern控制  
     从节点同步    
     通过长轮询请求,复制主节点oplog
  
     根据本地oplog日志的时间戳,在主节点oplog中找到新产生的数据(找不到同步点,说明相差太多,要重新同步)
  
     写入数据,更新本地oplog
  
     实现自动容灾    
     心跳信息    
     2秒 ping一次,用来实现 容灾和选举的判断
  
     节点挂了    
     挂从节点
    
     不处理  
     挂主节点    
     选举新主节点
  
     降级    
     主节点发现副本集只有自己,则自动降级为从节点  
     拒绝了写请求,可以避免数据无法冗余,丢失高可用  
     可以处理网络分区的问题,避免因为分区导致出现多个主节点    
     但不能完全避免,不一定只有主节点自身在一个网络分区,比如5个节点分成2+3  
     回滚    
     从节点复制时发现自己本地有主节点不存在的操作,则把这些操作回滚
    
     从节点之前是主节点,然后挂了,有数据没被复制  
     管理副本集    
     每次重新配置都会重新选主节点  
     重新配置过程    
     config= rs.config()
  
     config.members[1].host    
     假设修改第二个节点的host  
     rs.reconfig(config)  
     配置参数    
     priority    
     被选为主节点的优先级,0表示永远不做主节点  
     buildIndex    
     是否构建索引,备份节点不需要提供查询,设置为false  
     slaveDelay    
     复制的延迟时间,但是首先要配置节点优先级为0,才能生效  
     状态枚举    
     STARTUP    
     RECOVERING    
     FATAL    
     DOWN()    
     ROLLBACK  
     PRIMARY    
     SECONDARY    
     ARBITER  
     读写请求配置    
     写关注点
    
     默认为1  
     设置为0,存在风险,无法正常故障转移
  
     getLastError命令配置关注点    
     w    
     每次写要复制到几个服务器
  
     wtimeout    
     写请求复制到其他节点的超时时间  
     读偏好    
     primary    
     唯一保证一致性读的模式  
     只读主节点
  
     primaryPreffered    
     主优先,不可用读从库
  
     secondary    
     只读从库
  
     secondaryPreffered    
     从库优先  
     nearest    
     读响应延迟最低的节点  
     标签节点
    
     每个节点都可以被打上 若干tag
  
     通过getLastErrorModes命令,配置每次写到哪些标签,写标签中的几个节点    
     getLastErrorModes:{multiCity:{beijing:2},multiRegion:{us:3}}  
     定义了multiCity/Region两个模式,选择bj和us标签的节点
  
     第十二章 分片集群
    
     简介    
     分片集群结构    
     config service
    
     保存集群元数据,数据在集群上的分布信息  
     提供高可用的持久化存储    
     两阶段提交更新配置  
     shard (replica set)
    
     每个分片都是一个副本集  
     mongos进程    
     从config server读取节点,把客户端请求路由到合适的分片
  
     把配置数据写到config server,使用两阶段提交
  
     以独立进程运行,负责和客户端驱动连接
  
     数据分片方式    
     基于“块”分片,“块”包含一个集合中的一部分文档  
     一个集合的文档会分布在多个片上  
     维护分片集群    
     创建    
     1.创建副本集    
     mongod --shardsvr --replSet xxx
  
     2.创建config server
    
     mongod --configsvr xxxx
  
     3.启动mongos进程    
     mongos --configdb configserver(ip:port) xxx
  
     4.连接mongos进程,执行分片命令    
     sh.addShard(xxx)
  
     sh.enableSharding("shard db name")  
     sh.shardCollection("collection name",{分片键1,2,3...})    
     mongodb会在分片键上创建索引  
     数据迁移
    
     分割    
     当数据“块”chunk size超过64mb,会分割成两个”块“
  
     迁移    
     当数据在分片之间分布不均匀时发生  
     查看状态
    
     分片集群状态    
     sh.status()  
     集群变动日志
    
     use config; db.changelog.find()
  
     balancer工作机制    
     文档介绍  
     管理分片集群数据    
     分片键选择    
     不要产生热点    
     分片键要让数据分布均匀
  
     对查询友好,避免全局查询
    
     分片键最好是查询常用的字段  
     不要让分片数据块的粒度过粗
    
     分片键没有代表性,会使相同键的数据过多,超过分片单位"块"最大64mb的限制  
     不要使用objectID做分片键    
     objectID是自增的,新数据会集中到最后一个分片
  
     查询    
     分类    
     目标查询:查询包含分片键  
     全局查询:查询不包含分片键    
     需要在每个分片执行查询  
     通过explain命令查看是否为全局查询  
     索引    
     分片集合在每个分片上的索引字段是一样的  
     只能在分片键和_id字段创建 唯一索引
  
     部署最佳实践    
     减少使用的机器    
     副本集成员保存数据,需要单独的机器  
     副本集的裁判,不需要保存数据,可以和其他程序共享机器  
     config server实例,可以和其他程序共享机器
  
     优化方式    
     要保证config server每个实例实时在线
    
     当数量少于3台,配置服务器集群会变为只读,即没有主服务器,则分片集群不支持更改集群元数据的操作,例如块拆分和迁移。 虽然不能拆分或迁移任何块,但应用程序可以将数据写入分片集群(最多挂2台,否则停止服务)。  
     当加载大量数据到分片集合时怎样节省时间    
     使用预分割和预迁移的方式手动处理  
     添加分片耗时长    
     mongo集群,预估的数据迁移速度为100~200MB每分钟  
     在分片服务器内存占用到80%-90%之前就应该尽快提前迁移  
    
 
 
 
 
  0 条评论
 下一页
  
   
   
   
   
  
  
  
  
  
  
  
  
  
  
 