应用场景:大数据量,高并发,弱事务
面向文档型的数据库
第1章 简介
1.1丰富的数据模型
将原来行的概念换成更加灵活的“文档“的模型。
1.2容易扩展
1.3功能丰富
索引,存储javascript,聚合(mr),固定集合,文件存储
1.4不牺牲速度
mongoDB传输协议
预分配数据文件,空间换性能,内存映射文件,记住执行查询最高效的方式,
1.5简便管理
只要启动数据服务器就行,新增节点会自动集成和配置
1.6其他
愿景:建立一种灵活、高效、易于扩展、功能完备的数据库
第2章 入门
2.1文档
多个键及其关联的值有序地放置在一起便是文档。
键不能含有 \0(空字符),这个字符用来表示键的结尾
.和$有特别意义,最好不用
下划线_开头的键是保留的,最好不用
区分类型,区分大小写
键不能重复
2.2集合
集合就是一组文档
文档类似行,集合如同表
2.2.1无模式
集合是无模式的,一个集合里面的文档可以是各式各样的。
2.2.2 命名
我们可以通过名字来标识集合。集合名最好是utf8字符串
集合名不能是空字符串,不能含有\0,不能以system开头,不能含有保留字符$
子集合
组织集合的一种惯例是使用”.”字符分开的按命名空间划分的子集合。
2.3数据库
多个集合可以组成数据库。每个数据库有独立的权限和磁盘文件。
一个MongoDB实例可以承载多个数据库。
数据库名不能是空字符,不能呢含有空格,.,$,/,\,\0,应全部小写,最多64字节
admin相当于root数据库,存用户名,最高权限
local这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
config当mongo用于分片设置时,config用于保存分片的相关信息
命名空间(数据库名.集合名.子集合名)长度不得超过121字节,实际应用中应该小于100字节
2.4启动mongodb
Linux:./mongod
Windows:mongod.exe
默认27017为主端口,28017端口(比主端口号高1000)为监控页面端口
2.5 mongodb shell
2.5.1运行shell
./mongo
Shell是功能完备的javascript解释器,可以运行任何javascript程序,也可以定义和调用javascript函数。可以多行输入,会自动判断是否写完。
2.5.2 mongodb客户端
默认连接到test数据库,并将这个数据库连接赋值给全局变量db
2.5.3 shell中的基本操作
1、创建
先创建文档
再insert
2、读取
find会返回集合里面所有的文档,如果只想看一个,用findOne
3、更新
udate接受两个参数,第一个是要更新文档的限定条件,第二个是新的文档。
4、删除
Remove,不带参数删除集合内所有文档,带参数限定条件可以删除指定的一个。
2.5.4 使用shell的窍门
Db.help()帮助函数
输入函数时不输括号,会显示该函数的javascript源码
Db.getCollection(“name”);
x.y于x[‘y’]等价
2.6数据类型
2.6.1基本数据类型
Mongodb的文档类似于json,在概念上和javascript中的对象神似。
Null,布尔,32位整数(shell不支持),64位整数(shell不支持),64位浮点数,字符串,符号(shell不支持),对象id(是文档的12字节的唯一id),日期(从标准纪元开始的毫秒数),正则表达式(javascript的正则表达式语法),javascript代码,二进制数据(shell中无法使用),最大值(shell不支持),最小值(shell不支持),未定义,数组,内嵌文档
2.6.2 数字
Javascript只有一种,mongodb中有三种,shell绕开了这种限制,默认情况下shell中的数字都被当做双精度浮点数。所以即便原封不动存回数据,也会变成64位浮点数。
2.6.3 日期
New Date()是日期
Date(..)实际是返回字符串
2.6.4 数组
数组是一组值,既可以作为有序对象(像列表、栈或队列)来操作,也可以作为无序对象(像集合)来操作
2.6.5 内嵌文档
内嵌文档就是把整个mongodb文档作为另一个文档中键的一个值。这样数据可以组织的更自然些,不用非得存成扁平结构的。
会有重复信息,修改错误数据时需要在每一个文档中修改。
2.6.6 _id和ObjectId
Mongodb中存储的文档必须有一个”_id”键。这个键的值可以是任何类型的,默认是个ObjectId对象。在一个集合里,每个文档都有唯一的”_id”值,来确保集合里面每个文档都能被唯一标识。
1.ObjectId是”_id”的默认类型。不同的机器都能用全局唯一的同种方法方便的生成它。它有12字节的存储空间,每个字节两位16进制数字,是一个24位的字符串。
0~3时间戳,4~6机器,7~8pid,9~11计数器。所以同一秒钟最多允许每个进程拥有256的三次方(16777216)个不同的objectId。
2.自动生成_id
插入文档时没有_id键,系统会自动创建。可以由服务器来创建,但一般会在客户端由驱动程序完成。
第3章 创建、更新及删除文档
3.1插入并保存文档
Insert方法
3.1.1批量插入
批量插入能传递一个由文档构成的数组给数据库。
批量插入减少tcp请求数,并且无需处理大量的消息头
批量插入只是插入多个文档到一个集合时才会有用
如果只是导入原始数据,可以使用命令行工具mongoimport
当前版本的mongodb消息长度最大16mb
3.1.2插入:原理和作用
将数据转BSON,文档不超过4mb才插入,直接插入数据库,不做任何处理,数据可能无效,但可以远离注入式攻击
3.2删除文档
Db.users.remove();删除users集合中所有文档,不删除集合本身,索引也保留;
Db.mailing.list.remove({“opt-out”:true});删除所有optout为true的人;
删除数据是永久性的,不能撤销也不能恢复。
删除集合中的文档通常很快,但直接删除集合更快。
Db.drop_collection(“bar”);删除集合。
3.3更新文档
更新操作是原子的。默认情况下,更新只能对符合匹配条件的第一个文档执行操作。
1、
$inc增加计数操作,如果没有键会先创建
$set指定键值,如果没有次键会先创建
$unset取消键
2、数组修改器:
$push会向已有的数组末尾加入一个元素,如果没有会创建一个新的数组。
$ne如果一个值不在数组里就把它加进去。
$addToSet将值加入数组,可避免重复
$pop可以从任一端删除元素
$pull基于特定条件删除元素
3.数组的定位修改器
0或$,$只定位到第一个符合的记录
4.修改器速度
$inc立即修改,只修改值
$set在文档大小不会发生变化时也立即修改
$push比较多时会影响速度
3.3.3 upsert(update的第三个参数设为true)
Upsert是一种特殊的更新。如果没有文档符合更新条件,则以这个条件和更新文档为基础创建一个新的文档。
save 是一个Shell帮助函数,可以在文档不存在时插入,存在时更新。
3.3.4 更新多个文档(update的第四个参数设为true)
3.3.5返回已更新的文档
FindAndModify命令返回符合条件的更新前(也可设置为更新后)的文档,然后再更新(或删除)
3.4瞬间完成
插入,删除和更新都是瞬间完成的,他们不需要等待数据库响应。
3.4.1安全操作
安全的版本在执行完操作后立即运行getLastError命令,检查是否执行成功。
3.4.2捕获“常规”错误
3.5请求和连接
数据库会为Mongodb数据库连接创建一个队列,存放这个连接的请求。它们顺序执行。这个一个连接总可以读到自己写的东西。但多线程去连接就不一定能读到了了
第4章 查询
4.1find简介
Find的第一个参数决定了要返回哪些文档,不指定这个参数则返回全部内容
当我们开始向查询文档中添加键/值对时,就意味着限定了查找的条件。
4.1.1 指定返回的键
用第二个参数来指定想要(或不想要)的键
Db.users.find({},{“username”:1})
Db.users.find({},{“username”:0})
4.1.2 限制
查询文档的值必须是常量
4.2 查询条件
查询不仅可以精确匹配,还能匹配更加复杂的条件,如范围,or子句和取反
4.2.1 查询条件
$lt $lte $gt $gte 是全部的比较操作符,分别对应< <= > >=。
$ne 为不相等
可以将其任意组合,
Db.users.find({“age”:{“$gte”:18,”$lte”:30}})
4.2.2OR查询
$in可以用来查询一个键的多个值
$or更通用一些,用来完成多个键值的任意给定值
$nin 返回与数组中所有条件都不匹配的文档
4.2.3 $not
$not是元条件句,即可以用在任何其他条件之上,用来查找那些与条件不符的文档
4.2.4 条件句的规则
条件句是内层文档的键,而修改器则是外层文档的键。
一个键可以由多个条件,但是一个键不能对应多个更新修改器。
4.3特定于类型的查询
4.3.1 null
Null可以匹配自身,但是不仅仅匹配自身,还匹配“不存在的”。
如果仅仅想要匹配键值为null的文档,需要额外增加$exists条件判断
4.3.2正则表达式
Mongodb使用perl兼容的正则表达式(PCRE)库来匹配正则表达式。
4.3.3查询数组
绝大部分情况可以这样理解:每一个元素都是整个键的值。
1.$all
需要通过多个元素来匹配数组,需要用$all,顺序无关紧要。
要是想查询数组指定位置的元素,则需要使用key.index语法指定下标。
2.$size
可以用其查询指定长度的数组
3.$slice操作符
返回数组的一个子集合。
4.3.4 查询内嵌文档
通常只针对内嵌文档的特定键值进行查询才是比较好的做法。这样即便数据模式改变,也不会导致所有查询因为要精确匹配而一下子都挂掉,可以使用点表示法查询内嵌的键。
所以待插入的文档不能包含.。一种解决办法是在插入前或提取后执行一个全局替换,将.替换成其他字符
$elemMatch将限定条件进行分组,仅当需要对一个内嵌文档的多个键操作时才会用到。
4.4 $where查询
$where子句可以执行任意javascript作为查询的一部分。但是很慢,最好用索引根据非$where子句进行过滤,$where只用于对结果进行调优
4.5游标
数据库使用游标来返回find的执行结果。
4.5.1limit、skip、sort
Limit限制结果数量
Skip会略过前三个匹配的文档,返回余下的
Sort排序,参数为键值对,键是文档键名,值代表方向,1升序-1降序。
比较顺序:1最小值2null3数字4字符串5对象/文档6数组7二进制数据8对象id9布尔型10日期型11时间戳12正则表达式13最大值
4.5.2避免使用skip略过大量结果
1.不用skip对结果分页
2.随机选取文档
4.5.3高级查询选项
查询分为包装的和普通的两类。
高级条件:最多扫描的文档数量,查询的开始、结束条件,指定索引,获取查询细节而非数据,确保查询结果是在查询执行那一刻的一致快照等。
4.5.4获取一致结果
游标有可能会获得已经被挪动过的文档。具体见书p62
4.6游标内幕
看待游标有两种角度:客户端游标,数据库游标。
前面说的都是客户端游标
在服务器端,游标消耗内存和其他资源。结束遍历或受到客户端要求终止后才释放资源销毁自身。另外,如果10分钟没有使用,会超时销毁。客户端可以用immortal函数告知数据库不要让游标超时。
第5章 索引
5.1索引简介
Mongodb的索引几乎与传统的关系型数据库索引一模一样。
创建索引使用ensureIndex方法
没有索引时查询会做表扫描,查询整个集合,如果集合很大会非常慢。
若索引只有一个键,则方向无关紧要。若有多个键,则需要考虑每个索引的方向问题。
一般来说,如果索引包含了N个键,则对于前几个键的查询都会有帮助(从中间开始的查询不会有任何帮助)。
Mongodb的查询优化器会重排查询项的顺序以便利用索引。
创建索引的缺点就是每次插入,更新和删除时都会产生额外的开销。每个集合默认的最大索引个数为64个。
5.1.1扩展索引
建立索引时要考虑如下问题:
每个键的索引方向是怎样的?
如何应对扩展?
有没有种不同的键的排列可以使常用数据更多地保留在内存中?
5.1.2索引内嵌文档中的键
对内嵌文档的键索引与普通索引并无差异,两者也可以联合组成复合索引。
5.1.3为排序创建索引
因为无索引排序是有上限的,那就是不可能在内存里面做T级别数据的排序。
5.1.4索引名称
默认为keyname1_dir1_keyname2_dir2….这种形式,也可也自定义名字,推荐自定义
5.2唯一索引
唯一索引可以确保集合的每一个文档的指定键都有唯一值。
_id也是唯一索引,在创建集合时候创建,只是不能删除
如果没有对应的键,索引会将其作为null存储,如果插入多个缺少该索引键的文档,则由于文档包含null值而导致插入失败。
5.2.1消除重复
dropDups可以保留发现的第一个文档,删除接下来所有的重复值的文档
5.2.2复合唯一索引
创建复合唯一索引的时候,单个键的值可以相同,只要所有键的值组合起来不同就好。
5.3使用explain和hint
Explain会帮助你获得查询方面诸多有用的信息。只要对游标调用该方法,就可以得到查询细节。
Hint用来强制使用某个索引
Mongodb的查询优化器会在初次做某个查询时,同时尝试各种方案,最先完成的被确定使用并记录方案,其他终止。会定期重试其他方案,以防更新数据后此方案不是最新。
5.4索引管理
集合名和索引名加起来不能超过127字节
为已有文档创建索引比先创建索引再插入所有文档要稍快一些。
删除索引前要先查看system.indexes中索引的名字,按名字删除。
5.5地理空间索引
Mongodb为坐标平面查询提供了专门的索引,称作地理空间索引。参数不是1和-1而是2d。
默认范围-180~180,如需增加需要另外加参数。
查询条件用$near,查询会按给定坐标由近及远的方式将map集合的所有文档都返回。
GeoNear也可以完成同样的操作,还会返回每个文档到查询点的距离,但是如果结果大于4mb则只能用find+$near的方式。
另外,还可以寻找指定形状内的文档,$within方法,$box可以搜索矩形,$center可以搜索圆形。
5.5.1复合地理空间索引
可以用地理空间索引和普通索引组合
5.5.2地球不是二维平面
第6章聚合
简单的可以计算集合中的文档个数,复杂的可利用mapreduce做复杂数据分析。
6.1count
Count是最简单的聚合工具,返回集合中文档数量。
直接count很快,增加查询条件会使得count变慢。
6.2 dinstinct
Dinstinct用来找出给定键的所有不同的值。
6.3 group
Mongodb会将集合依据选定键值的不同分成若干组,然后可以通过聚合每一组内的文档,产生一个结果文档。
添加condition可以只处理满足条件的文档(类似于where)。
6.3.1 使用完成器
finalize完成器用以精简从数据库传到用户的数据。
Finalize在每组结果传递到客户端之前被调用一次。
6.3.2 将函数作为键使用
定义分组函数要用到$keyf键
6.4 MapReduce
mr比group更慢,绝不要使用在实时环境中。
6.4.1 例1:找出集合中的所有键
Mr结果放在临时集合汇总,mr的连接关闭后自动就被删除了。
6.4.2 例2:网页分类
6.4.3 mongodb和mapreduce
Mapreduce可选函数:
Finalize函数,将reduce结果发送给这个键,这是处理过程的最后一步。
Keeptemp布尔,连接关闭时临时集合是否保存
Output 字符串:结果集合的名字。该设定隐含keeptemp:true
Query 文档:发往map函数前,先用指定条件过滤文档
Sort 文档:发往map前先给文档排序(与limit一同使用非常有用)
Limit 整数:发往map函数的文档数量的上限
Scope 文档:javascript代码中要用到的变量
Verbose 布尔:是否产生更加详尽的服务器日志。
每个传递给map函数的文档都要事先反序列化,从BSON转换成javascript对象。
第7章 进阶指南
7.1数据库命令
7.1.1命令的工作原理
Mongodb中的命令其实是作为一种特殊类型的查询来实现的,这些查询针对$cmd集合来执行。但不是普通的查询代码,而是一套特殊逻辑。
7.1.2 命令参考
7.2固定集合
固定集合很像环形队列,如果空间不足,最早的文档会被删除。
有些操作不适用于固定集合:不能删除文档(除了队尾自动淘汰),更新不得导致文档移动(通常更新意味着尺寸增大)。
固定集合没有索引,甚至连_id索引都没有。
7.2.1属性及用法
插入速度极快
按照插入顺序输出的查询速度极快。
一般来说,固定集合适用于任何想要自动淘汰过期属性的场景,没有太多的操作限制。
7.2.2创建固定集合
固定集合必须显示地创建
也可以通过转换已有的普通集合的方式来创建固定集合
7.2.3自然排序
自然顺序就是文档在磁盘上的顺序
7.2.4 尾部游标
尾部游标是一种特殊的持久游标,这类游标不会在没有结果后销毁。尾部游标只能用在固定集合上。
7.3 GridFS:存储文件
GridFS是一种在mongodb中存储大二进制文件的机制。
7.3.1 开始使用gridFs:mongofiles
7.3.2 通过mongodb驱动程序操作gridFs
7.3.3 内部原理
Gridfs是一个建立在普通mongodb文档基础上的轻量级文件存储规范;
Gridfs的一个基本思想就是可以将大文件分成很多块,每块作为一个单独的文档存储,这样就能存储大文件了。
7.4 服务器端脚本
7.4.1 db.eval
利用db.eval可以在mongodb的服务器端执行任意的javascript脚本
这个函数先将给定的javascript字符串传送给mongodb(在这里执行),然后返回结果
Db.eval可以用来模拟多文档事物:db.eval锁住数据库,然后执行js,再解锁
7.4.2 存储javascript
每个mongodb的数据库中都有个特殊的集合,叫做system.js,用来存放javascript变量和函数。
7.4.3 安全性
使用不慎,就会发生类似于关系型数据库的注入式攻击。
7.5 数据库引用
7.5.1什么是DBRef
DBRef是个内嵌文档,唯一标识数据库中的一个文档,类似url。
7.5.2 示例模式
7.5.3 驱动对DBRef的支持
不是所有驱动程序都将DBRef作为普通的内嵌文档。
7.5.4 什么时候该使用DBRef呢
使用一些对不同集合的文档的引用时,最好使用DBRef,或者想使用驱动程序或者工具中DBRef特有的功能,只能用DBRef了。否则,最好存储_id作为引用来使用,因为这样更精简,更易操作。
第8章 管理
8.1启动和停止mongodb
8.1.1从命令行启动
执行mongod,启动mongodb服务器。Mongod –help可以查看所有可选项。
因为使用内存映射文件存储引擎,所以32位的mongodb只能处理2gb的数据。
8.1.2配置文件
Mongodb支持从文件获取配置信息。
8.1.3 停止mongodb
可以使用shutdown命令,在admin数据库下,db.shutdownServer();
或者前台程序直接ctrl-c,后台程序用kill -2 pid
Kill -9 有可能会使数据文件损毁!
8.2监控
8.2.1使用管理接口
管理接口比主服务的接口大1000,默认http://localhost:28017
8.2.2 serverStatus
db.runCommand({“serverStatus”:1})
8.2.3 mongostat
Mongostat输出一些serverStatus提供的重要信息每秒钟输出新的一行
8.2.4第三方插件
8.3 安全和认证
8.3.1 认证的基础知识
Admin库中的为超级用户,其他的库可以添加普通用户,可以指定是否只读用户。
8.3.2认证的工作原理
用户账号以文档的形式存储在system.users集合里面。
8.3.3其他安全考虑
Mongodb传输协议是不加密的。如有需要客户端和服务器端需要做加密。
8.4备份和修复
8.4.1数据文件备份
简单将数据文件备份就可以,但是需要关闭数据库,否则很可能是破损的数据文件。
8.4.2 mongodump和mongorestore
Mongodump运行时备份,对运行 的mongodb做普通的查询,并备份,会对其他请求产生效率上的不利影响。
./mongodump –help
Mongorestore可以把利用mongodump备份的数据插入到数据库实例中。
8.4.3 fsync和锁
Fsync强制刷新
8.4.4 从属备份
从服务器上的数据几乎和主服务器同步,所以可以将上述方法直接在从服务器上灵活使用。在从服务器备份是mongodb推荐的备份方式。
8.4.5修复
停电或软件崩溃有可能造成mongodb数据损毁
Mongod –repair来启动服务器会修复数据
修复过程:将所有文档导出然后马上导入,忽略无效的文档,完成后,重建索引。
修复运行中的服务器上的数据库,要在shell中使用repairDatabase
第9章 复制
不仅可以用复制来应对故障切换、数据集成,还可以用来做读扩展、热备份或作为离线批处理的数据源。
9.1 主从复制
Mongod --master启动主服务器
Mongod –slave –source master_address则启动了从服务器,master_address为主节点的地址
所有从节点都从主节点复制内容,目前还不能从从节点复制,原因是从节点不保存自己的oplog。一个集群中最好不超过12个从节点,这样集群才可以运转良好。
9.1.1选项
--only 在从节点上指定只赋值特定某个数据库(默认复制所有数据库)
--slavedelay 在从节点上应用主节点的操作时增加延迟(单位是秒)
--fastsync以从节点的数据快照为基础启动从节点,这样会比较快(省去很多同步工作)。
--autoresync如果从节点与主节点不同步了,自动重新同步
--oplogSize主节点ooplog的大小(单位mb)
9.1.2 增加及删除源
可以操作sources集合
要是使用一个从节点对应多个不同的主节点,最好在主节点上使用不同的命名空间,因为从不同主机同步的相同集合会尝试合并,但不保证能正确合并。
9.2 副本集(不知道是否已经进入生产版本)
副本集就是有自动故障恢复功能的主从集群。
没有固定的主节点:整个集群会选举出一个主节点,当其不能工作时则变更到其他节点。副本集总有一个活跃节点和一个或多个备份节点。
9.2.1 初始化副本集
使用—replSet选项,如果副本集名字设为blort
./mongod –dbpath ~/dbs/node1 –port 10001replSet blort/morton:10002
./mongod –dbpath ~/dbs/node2 –port 10002replSet blort/morton:10001
如果再增加一台
./mongod –dbpath ~/dbs/node3 –port 10003replSet blort/morton:10001
只需指定一个,他们会自动关联到一起。
初始化副本集:
./mongo morton:10001/admin
Db.runCommand() {具体参考书上}
9.2.2副本集中的节点
Standard常规节点,存储一份完整数据副本,参与选举,有可能成为活跃节点
Passive存储了完整的数据副本,参与投票,不能成为活跃节点
Arbiter仲裁者只参与投票,不接收复制的数据,也不能成为活跃节点。
9.2.3故障切换和活跃节点选举
优先级最高且数据最新的服务器成为新的活跃节点
活跃节点使用心跳来跟踪集群中有多少节点对其可见,若不够半数,活跃节点会自动降为备份节点。
新活跃节点数据被假定为最新数据,其他需要从新和他同步,必要时(从以前的活跃节点同步的最新数据)需要回滚。
9.3在从服务器上执行操作
9.3.1读扩展
将查询放在从节点上,主节点的负载就减轻了,读取密集型这是非常不错的方案。
有个要点,数据复制并不同步。主节点插入和更新后,从节点有片刻时间数据不是最新的。
需要设置slaveOkay
9.3.2 用从节点做数据处理
--slave –master选项,可以写入,查询。
9.4 工作原理
主节点负责处理客户请求,从节点负责映射主节点的数据。
9.4.1 oplog
主节点的操作记录成为oplog,oplog存在特殊的数据库local中的oplog.$main集合中。
9.4.2同步
从节点第一次启动时会对主节点数据进行完整同步。完成后,开始查询主节点的oplog并执行这些操作以保证数据是最新的。
从节点跟不上同步速度时,就会停下。折中办法是oplog的大小设置大一点。
9.4.3复制状态和本地数据库
本地数据库local用来存放所有内部复制状态,主节点和从节点都有。其内容不会被复制。
9.4.4阻塞复制
Db.runCommand({getLastError:1,w:N});
如果没有N或小于2,命令就会立刻返回,如果等于2,主节点至少要等一个从节点复制了上个操作命令才会相应命令(主节点本身也包括在N里面)。
会导致写操作变慢,重要操作其值设为2或3就可以兼顾效率与安全了。
9.5管理
9.5.4诊断
主节点Db.printReplicationInfo();
从节点db.printSlaveReplicationInfo();
9.5.2变更oplog大小
变更oplog大小后,所有从节点得用—autoresync启动,否则需要手动重新同步
9.5.3复制的认证问题
如果启用了认证,需在本地数据库增加repl用户才行
第10章 分片
分片是mongodb的扩展方式,可以增加更多的机器来应对不断增加的负载和数据,还不影响应用。
10.1分片简介
分片(sharding)或分区(partitioning),是将数据拆分,分散在不同的机器上的过程
10.2自动分片
Mongodb分片的基本思想是将集合切分成小块。这些块分散到若干片里,每个片只负责总数据的一部分。
应用程序不必知道细节,分片之前需要运行一个路由进程mongos,它知道数据和片的对应关系。
何时分片:单机的磁盘不够用了;单个mongod已经不能满足写数据的性能需要了;想将大量数据放在内存中提高性能。
10.3 片键
设置分片时,需要从集合里选一个键,应用该键的值作为数据拆分的依据。
按流量平衡数据。(流量较大的片存放的数据会比其他片少些)
10.3.1将已有的集合分片
10.3.2递增片键还是随机片键
指入库时是否会充足利用集群资源,还是只入到最新的那个片键中。
按日期的键会成为递增片键,写效果不好;按哈希值会成为随机片键。
如果某个键只有3个值,则无论如何也无法将这个集合分成多余3块,解决办法是可以创建复合片键。
10.3.3片键对操作的影响
按片键查询会比较高效,可以直接定位到相应的片
如果按非片键的键查询,则mongos会在所有片上查询
10.4建立分片
10.4.1启动服务器
首先需要启动配置服务器和mongos
然后添加片,片就是普通的mongod实例(或副本集)
当在localhost上运行片时,得设定”allowLocal”键让它知道这仅仅是开发。
10.4.2切分数据
Mongodb不会将存储的每一条数据都直接发布,得先在数据库和集合的级别将分片功能分别打开。
10.5生产配置
10.5.1健壮的配置
多个配置服务器,配置服务器使用的是两步提交机制,而不是普通的mongodb的异步复制,这样能保持集群状态的一致性,如果有一台配置服务器宕机,集群配置信息将是只读的,只有所有配置服务器恢复并且备份了以后才能重新均衡数据。
10.5.2多个mongos
Mongos的数量不受限制。建议针对一个应用服务器只运行一个mongos进程。这样每个应用服务器就可以与mongos进行本地会话。
10.5.3健壮的片
生产环境中,每个片都应是副本集。
10.5.4物理服务器
只要保证互为备份的那些进程不在同一个服务器中即可。比如可以把一个配置服务器,一些mongos进程和副本集的一个节点放到一台机器上。
10.6管理分片
分片信息主要存放在config数据库上
下几节默认运行了use config
10.6.1配置集合
1.片 :片在shards集合中
2.数据库:数据库在databases集合中
3.块:块信息保存在chunks集合中
10.6.2分片命令
1.获得概要
Db.printShardingStatus()
2.删除片
Removeshard就能从集群中删除片,会把给定片上的所有块都挪到其他片上。
在1.6.0版本中如果删除的片是数据库的大本营(基片),必须手动移动数据库(使用moveprimary命令)
第11章 应用举例
Java驱动程序是mongodb最早的驱动,是企业级开发的首选
如果索引比较多可以单独建立一个index键,将所有需要索引的属性放入
建立文档并存入的过程比较繁琐
如果查询时含有多个条件,条件的顺序很重要,mongodb的索引只会应用到条件句的第一项,其他的还是扫描方式获得,所以要确定好条件顺序。
附录C 深入mongodb内部
1.BSON
Mongodb 的文档是 binaryJSON(BSON)
BSON是轻量的二进制格式,能将mongodb的所有文档表示为字节字符串。
用BSON的主要目标:效率,可遍历性,性能(编码解码速度快)
2.mongodb传输协议
TCP/IP协议的基础上简单封装了mongodb传输协议,基本上就是一个简单封装的BSON数据。例如,插入时会有20字节的头部数据(插入代码,消息长度等)、要插入的集合名、要插入的BSON文档列表。
3.数据文件
每个数据库都有几个独立文件,.ns文件(存放元数据)和以数字结尾的文件。例如test库有test.ns,test.0,test.1,test.2等。每个新的以数字结尾的数据文件大小会加倍,知道达到最大的2gb?为了不让小的浪费空间,同时让大的使用磁盘上的连续空间。
还会预分配数据文件,避免文件分配产生的阻塞。
4.命名空间和数据域
每个集合的文档都有自己的命名空间,索引也是。
每个命名空间的数据都被分成若干组,放到数据文件的某一区域内,这个区域称为数据域。
特殊的命名空间$freelist存放着不住使用的数据域(例如删除集合或索引产生的数据域)。命名空间分配新的数据域时,系统会先查找空闲列表,看看有没有合适大小的数据域可用。
5.内存映射存储引擎
当服务启动后,将所有数据文件映射到内存。然后由操作系统来负责将缓冲数据写入磁盘并将数据调入调出内存页面。
32位的每个mongod最多只能处理2gb数据