celery笔记 jieba RPC 服务 http2 vs http1 python发送邮件 gitbook 笔记 docker运行 pyppeteer 百度/腾讯 ocr 试用 页面元素选择 python pickle 实践 k3s 安装加速 FFmpeg 使用总结 Systemd 教程 mysql 1366 错误解决 docker-compose 笔记 sqlite 使用总结 百度网盘命令行工具 bypy 阿里云 PAI-EAS 试用报告 gpt2中文预训练模型试用 文本生成资料汇总 使用 tracemalloc 分析 python 内存使用情况 spark 集群试用 openresty使用笔记 mac下 python 报错 CERTIFICATE_VERIFY_FAILED docker-compose 安装方法 系统代理 mac 下安装 adb scrapy项目作为工具库使用 charles over proxy 使用 markdown 制作 ppt docker挂载目录异常 flask 笔记 wsl2 使用体验 nginx 配置 mac 配置 发布自己的 python 包 selenium + chrome 全页面截图 mongo ORM 笔记 supervisor 使用总结 h5py性能测评 privoxy实现PAC代理上网 session请求示例 ssh笔记 python小技巧 docker学习笔记 tornado使用总结 再读《MongoDB权威指南》 tornado文件上传服务 mongo学习笔记 python异步服务器测试 No module named 'Crypto' on Mac mac中安装python3.5 py3.6环境下numpy C扩展出错 mtcnn读书笔记 shell 学习笔记 install ubuntu18.04 定时备份linux系统的history记录 asyncio异步请求示例 golang setting git使用笔记 Ubuntu16.04下配置python3环境 将Ubuntu16.04升级为Ubuntu18.04(development branch) Ubuntu16.04下源码安装python3.6 virtualenv中安装anaconda模块 基于sqlite3实现数据缓存 修复colaboratory中tensorflow的bug 安装docker-compose docker引起的空间不足 CNN可视化研究 ubuntu16.04中安装wine-qq 在ubuntu16.04中安装wine3.0+winetricks ssh over socks5 python删除文件或目录 shadowsocks+privoxy设置本地代理 python下载大文件的方法 解决python中遇到的乱码问题 修改 ubuntu & windows双系统中系统启动顺序与等待时间 python3安装mysql ubuntu环境变量设置 python 后台程序实现

再读《MongoDB权威指南》

2019年03月24日

再读《MongoDB权威指南》

刚接触mongo时,所看过最好的入门资料,就是《MongoDB权威指南》. 阅读后, 对mongo有一个直观的了解, 配合mongo官方文档, 使用mongo就没什么困难了.

最近新项目, 需要深度使用mongo, 如使用复杂的聚合操作生成报表数据. 项目中还遇到聚合操作形成数据库全局锁, 导致其他操作被阻塞的问题.

空闲之下, 决定再读《MongoDB权威指南》, 加深理解.

1. Mongo简介

  • 聚合操作, 数据库能自动优化
  • 支持存在时间有限的集合, 适合session管理等场景
  • 支持固定大小的集合,适合保存日志等场景
  • 支持一种协议,用于存储大文件和文件元数据(?)

2. MongoDB基础知识

  • objectId能提取时间戳

3. 创建 更新和删除文档

  • 删除集合最快的方法: drop + 重建索引
  • 更新操作不可分割: 原子性
  • array vs set. $push 对array添加元素; $addToSet将array当做set并添加元素; 前两者配合$each实现添加多个元素
  • 删除元素: $pop vs $pull, 具体参考官方文档.
  • $基于位置的数组修改器定位符. db.blog.update({"comments.author" : "John"},{"$set" : {"comments.$.author" : "Jim"}}), 定位符只更新第一个匹配的元素
  • 修改器速度: mongo为文档大小预留空间; 当文档修改后大小不够,会执行文档移动操作.
  • 批量更新文档,获取更新信息: ` db.runCommand({getLastError : 1}) # “返回最后一次操作的相关信息`.
  • 写入安全(Write Concern), 有两种模式, 应答式(确认成功)和非应答式(不返回响应). 非应答式用于不重要数据存储场合.

4. 查询

  • 返回制定键, 默认返回_id. ` db.users.find({}, {“username” : 1, “email” : 1}) # 返回三个键, db.users.find({}, {“fatal_weakness” : 0}) # 不返回指定键`
  • 高级查询, 参数及示例.
  • $where, 借用js. 但速度慢, 如无必要, 不要使用.
  • 服务端脚本, 容易受到攻击.
  • 避免使用skip略过大量结果, skip大量结果, 很占资源. 可行的方法是, 利用上一次查询的条件, 略过已查询的结果.
  • 高级查询选项: $min, $max能强制使用索引, 具体参考书本. $maxscan, 扫描文档上限.
  • 游标, 获取一致性结果. cursor = db.foo.find();while (cursor.hasNext()) {...}, 相同的结果可能返回多次, 原因是文档修改后空间不足可能被移动到后面. 解决方法是使用快照 db.foo.find().snapshot(), 但占资源, 尽量不用.
  • 服务端游标的生命周期. 一般客户端会通知销毁游标; 服务端有超时记录, 超时后会自动销毁, 如果客户端需要长时间使用游标, 需要告知服务端不要超时销毁.

5. 索引

  • explain查看具体执行操作, 调试索引的好工具. 如 db.users.find({username: "user101"}).explain()
  • db.currentOp() 如果新建索引不能短时间内返回结果, 可以另开shell执行db.currentOp()查看
  • 索引的代价: 每次操作, 需要更新索引, 耗时更长. mongo限制索引上限为64; 每个集合最好不超过两个索引.
  • hit(): 强制 MongoDB 使用特定的索引
  • 稀疏索引: sparse. ` db.ensureIndex({“email” : 1}, {“unique” : true, “sparse” : true})`, email存在, 则唯一.

6. 特殊的索引和集合

  • 固定集合: 固定大小, 循环队列.
  • TTL索引, 这种索引允许为每一个文档设置一个超时时间. 一个文档到达预设置的老化程度之后就会被删除. 这种类型的索引对于缓存问题(比如会话的保存)非常有用. db.foo.ensureIndex({"lastUpdated" : 1}, {"expireAfterSecs" : 60*60*24}) # 24h
  • 全文本索引, 用于全文检索, 耗资源.
  • 地理空间检索, 最常用的是 2dsphere 索引(用于地球表面类型的地图)和 2d索引(用于平面地图和时间连续的数据). 支持交集, 包含和接近查询.
  • GridFS存储文件.

7. 聚合

TODO: 待补充

17. 了解应用的动态

  • db.currentOp(): 查看正在进行的操作
  • db.killOp(): 终止操作. 注意, 只有交出了锁的进程才能被终止
  • system profiler: 可获得慢查询日志, 该操作默认不打开
  • stats: 获取集合, 数据库状态信息
  • mongotop 类似top, 获取当前操作信息. mongotop-locks, 获得每个数据库的锁状态

18. 数据管理

  • 权限控制: 颗粒度
  • 建立索引: ` db.foo.ensureIndex({“somefield” : 1}, {“background” : true})`. 前台建索引, 锁定数据库; 后台建索引, 定期释放写锁
  • 压缩数据: 数据碎片; 使用 db.runCommand({"compact" : "collName"})压缩数据