读书笔记 3 -- 《MongoDB实战》
有感:
1、数据库在速度与持久性之间的妥协:
磁盘io分为:
1.1、顺序IO(高效)
1.2、随机IO
因此引入:事务日志。
当存储一个数据时,双写:
a、RAM(随机IO)
b、事务日志(写入成功,代表数据存储完成。)(顺序IO)
定时刷RAM的数据到磁盘中,完成持久化。
关系型数据库:(适用)
1、复杂数据模型,复杂查询。
what?是什么
文档模型(json),直观的数据模型。
非关系型,无事务。
可扩展行(分片),伸缩。
mongodb的无事务体现:
1、写入RAM即返回确认结果。
2、写入到各个可复制集群节点,再返回确认结果。
3、fire-and-forget,客户端发送写入结果,mongodb接收到后,立即返回确认结果。(未写入RAM中)
定时刷RAM的数据到磁盘,完成数据的持久化。
原子更新:单条数据,支持事务操作。要么成功,要么失败。
盖子集合:(capped collections)类似循环数组。
TTL:time-to-live
适用场景:
数据量大,无事务,非关系型,低价值的数据。
数据库系统建模的思考:
1、使用的模式是什么?读写的比率是多少?查询是否简单?是否需要聚合查询?数量是多少?等等问题……
2、数据的基本单位是什么? 表?还是文档?
3、数据库的功能是什么?MongoDB不支持join链接查询。
4、数据主键的选择。
数据库文件和分配:
1、文件路径:dbpath(默认:/data/db)
2、mongod.lock
3、xxx.ns 命名空间。
Mongodb快速的原因:
1、将索引全部加载到内存中。
文档:
限制:
1、16MB大小。原因:性能相关。
投影:
就是你想要mongodb返回哪些字段。
how?怎么用
版本:
1、偶数稳定版。奇数为开发版。
核心服务:
1、mongod 核心服务。存储数据的服务,裁判。
2、mongos 路由服务。分片集群中转发不同的请求到mongod服务。
语法:
命令:
1、update
1.1、$set (有则修改,无则新增)
1.2、$unset (删除字段)
1.3、$push(往数组中添加数据)
1.4、$addToSet(往数组中添加数据,防止重复数据)
2、remove(删除数据,不删除集合)
3、drop(删除集合)
4、save,insert
5、count
6、find
7、createIndex
8、explain -- > executionStats
9、$slice 选择返回文档的子集
10、group
11、project 过滤传递给下一个管道的字段。
12、unwind 更快速的链接。为每个输入文档的数组生成一个输出文档。
基本管理命令
1、show dbs;
2、show collections;
3、db.stats()
驱动工作原理:
1、生成MongoDB对象ID。
2、文档 <--> BSON(二进制JSON)
3、TCP socket与数据库通信。(socket通信应答机制)
对象ID:
1、格式:4B时间 3B机器ID 2B进程ID 3B计数器
聚合:(mysql: group by)
1、管道:输出作为别的输入。
2、聚合管道的命令
2.1、project 指定输出文档的字段。
2.2、match 选择要处理的文档,与find类似。
2.3、unwind 扩展数组,为数组入口生成一个输出文档。
2.4、group 根据key来分组文档。
2.5、out 把管道的结果写入某个集合。
2.6、redact 控制特定数据的访问。
文档更新:
1、findAndModify
索引:
1、稀疏索引
索引值,可以为空(null),为null的值不添加到索引中。sparse:true
2、密集索引(默认)
一个索引入口对应一个文档。
3、多键索引
多个索引入口指向同一个文档。(数组的索引)
4、哈希索引
先哈希,再根据哈希值建立索引。
优点:入口均匀分布。配合分片使用,实现数据均匀分布。
缺点:不支持范围查询、不支持多建哈希、浮点需要转换为整型再哈希(因此4.2=4.3)
5、单件索引:最好是越分散越好。
组合索引:在前面的索引,越聚集越好。
存储引擎:存储引擎是数据库与硬件直接的接口。
mongodb数据库:可插拔存储引擎api --> 存储引擎
MMAPvl: 基于内存映射。
缺点:随着数据的增长,快速的消耗大量的磁盘空间。预分配2G内存。
WiredTiger:
优点:
1、存储空间小。
2、可选择压缩模式。存储更小,读取更快。
复制:(主从)
可复制集群:在主从的基础上,增加了自动化备灾机制。如果主节点宕机,无论什么原因,其中一个从节点自动提升为主节点。
复制的缺点:
回滚机制。
主完成写入,从未写入,此时主宕机。那么从的数据,就是不完整的。
解决方法(从机器过半写入):超过一半的从机,完成写入操作。
分片:
什么是分片:分片是把大型数据集进行分区成更小的可管理的片的过程。
何时需要分片:1、存储分布式。2、负载分布式。
集群分片的组件:
1、shard-a,shard-b 存储数据的组件。
2、mongos 路由组件。路由到正确的分片。
3、配置服务器组件。存储集群元数据,哪个分片包含哪些数据集。
分片的粒度:
1、文档。2、块(多个键组合而成)。3、集合。4、数据库。
分片的种类:
1、数据库分片。
2、集合分片。
启用数据库分片:(需要手动分片) sh.enableSharding('dbname');
设置分片的集合:sh.shardCollection('dbname.collectionName',{filed1:1,filed2:1})
查看分片集合:db.getSiblingDB('config').collections.find()
查询、索引如何跨片工作:
1、查询:
1.1、目标查询:查询包含分片键。
1.2、全局查询:查询不包含分片键。
2、索引
2.1、每个分片维护自己的索引。
2.2、分片集合只允许在_id字段和分片键上建立唯一索引。禁止别的键建立唯一索引。
分片集群key的选择:
1、陷阱:
1.1、热点:如果分片的键不够分散,则回造成单台机器数据过多的问题,而有些机器又过于清闲。
1.2、不可分割的数据库(粗粒度):如果一个键粒度太粗,则当该粒度大于64M时,无法进行跨集群迁移。
1.2、糟糕的查询:能分散,但是不利于查询的情况。
2、理想的分片键:
2.1、方便定位数据。
2.2、分布的数据。
2.3、高效的分割和迁移数据。
3、理想分片键的实现:
3.1、理想的分片键有点类似cap理论,只能3选2。
3.2、使用组合键的方式,满足上述要求。键1够分散,键2升序(参考_id键)。
why?为什么
待补充