MongoDB: db-collection-document
MongoDB更类似Mysql,支持字段索引、游标操作,其优势在于查询功能比较强大,擅长查询JSON数据,能存储海量数据,但是不支持事务。
内存管理机制:MongoDB数据存在磁盘上,数据库启动后将数据以文件映射(由linux mmap()实现)的方式加载中到内存中,当内存不够时,只将热点数据放入内存,其他数据存在磁盘。
http://huoding.com/2011/08/19/107
Linux系统,内存分物理内存和虚拟内存,虚拟内存是物理内存的抽象,程序访问虚拟内存地址,然后操作系统通过Page Table机制翻译到物理内存地址。Swap交换空间不是虚拟内存,而是虚拟内存引申出的一种技术。当物理内存不足时,为腾出内存空间存放新内容,将当前物理内存中的内容放到Swap交换空间中,需要时再取回物理内存中。Swap的使用可能带来性能问题,因为需要频繁交换物理内存和Swap的内容,可增加物理内存解决。
MongoDB使用内存映射存储引擎,将数据文件映射到内存中。对于读操作,内存中的数据起到缓存作用,对于写操作,内存可以把随机的写操作变成顺序的写操作,提高性能。MongoDB的内存使用是由操作系统的虚拟内存管理器控制的(LRU算法淘汰冷数据)。
MongoDB优点:
1、弱一致性(最终一致),访问速度快
2、文档结构存储,不用定义复杂表结构,查询方便
4、性能优越,大数据量下优于关系型数据库
4、存储对象为BSON,不可被解析,安全,防范SQL注入攻击
5、扩展性好
×、自带分布式文件系统GridFS,自带对map-reduce的支持、
MongoDB缺点:
1、不支持事务操作
跟优点1对应
2、占用空间过大
1、空间预分配:mongodb每次空间不足都会申请一大片空间,申请空间大小指数级递增
2、字段名占空间:为保证每一条记录都包含结构数据,每一个字段都以key-value的形式保存
3、删除记录不释放空间:防止数据删除后其他数据的大规模挪动;原记录空间不删除,只标记为已删除;只有db.repairDatabase()后才释放,但修复时间很长
MongoDB VS MySQL
主键:_id PRIMARY KEY
索引:优化查询性能,尽量选择小的、简单的(整型优于字符型)、非NULL的数据类型创建索引
查询速度:MongoDB充分利用内存资源,查询效率远高于通过磁盘I/O的MySQL
插入:MongoDB插入效率略高(不指定_id插入,此时_id自动生成,对相关字段做索引查询),指定_id插入效率极低
MongoDB操作:
索引
默认为_id建立索引,不可删除。索引分升序(:1)降序(:-1)。只有参数顺序相同的查询会用到对应的索引。
数据量大后建立索引很慢,可以后台执行,只需要加上参数 {backgroud:true}。
> db.test.ensureIndex({t:1},{backgroud:true}) // 建立索引
> db.test.ensureIndex({tt:1},{unique:true}) // 唯一索引,不允许插入重复键值
> db.test.ensureIndex({t:1,tt:1}) // 组合索引
> db.test.getIndexes() // 查看集合test下所有索引
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "smartstock.test",
"name" : "_id_"
},
{
"v" : 1,
"key" : {
"tt" : 1
},
"unique" : true,
"ns" : "smartstock.test",
"name" : "tt_1"
},
{
"v" : 1,
"key" : {
"t" : 1,
"tt" : 1
},
"ns" : "smartstock.test",
"name" : "t_1_tt_1"
}
]
> db.test.find({"t":{$lt:30}}).hint({t:1, tt:1}) // hint强制使用索引
> db.test.find().sort({t:1,tt:1}); // 查询并排序,升降序同索引
> db.test.dropIndexes(tt_1) // 删除单个索引
> db.test.dropIndexes() // 删除所有索引
查询
插入
修改
删除
性能分析Explain
> db.test.find()
{ "_id" : ObjectId("5618e0ed808f3d701fb0467c"), "t" : "1" }
{ "_id" : ObjectId("561b47c0808f3d194bf0d2fd"), "t" : "1", "tt" : "2" }
> db.test.ensureIndex({"t":1})
> db.test.find({"t":1}).explain()
{
"cursor" : "BtreeCursor t_1",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 0,
"nscanned" : 0,
"nscannedObjectsAllPlans" : 0,
"nscannedAllPlans" : 0,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 9,
"indexBounds" : {
"t" : [
[
1,
2
]
]
},
"server" : "TZ-IT-Yanym:27017"
}
cursor: 返回游标类型,BasicCursor(遍历游标) 或 BtreeCursor(B树游标)
nscanned: 被扫描的文档数量
n: 返回的文档数量
millis: 总耗时(毫秒)
indexBounds: 所使用的索引
性能监控工具
1、mongosniff 此工具可以从底层监控到底有哪些命令发送给了MongoDB 去执行,从中就可以进行分析:
以root 身份执行:$./mongosniff --source NET lo
然后其会监控位到本地以localhost 监听默认27017 端口的MongoDB 的所有包请求。
2、mongostat 实时查看MongoDB实例的运行状态信息,每秒刷新一次
insert: 每秒插入量
query: 每秒查询量
update: 每秒更新量
delete: 每秒删除量
locked: 锁定量
qr | qw: 客户端查询排队长度(读|写)
ar | aw: 活跃客户端量(读|写)
conn: 连接数
time: 当前时间
3、db.serverStatus() 查看数据库实例运行状态
db.serverStatus().connections 查询连接数,连接数过多会拖累性能
db.serverStatus().mem 查询内存使用情况,还可以使用mongostat命令查看,mapped:映射到虚拟内存的大小,virtual:占用的虚拟内存大小,resident:占用的物理内存大小,faults:每秒访问失败数,faults高时性能下降
4、db.stats() 查询数据库状态信息:数据大小,索引大小
COMMANDS:
db.listCommands()
db.repairDatabase() / db.runCommand({repairAllDatabase:1}) MongoDB碎片整理(产生锁,对磁盘空间需求大)
db.runCommand({closeAllDatabases:1}) (先use admin) 释放MongoDB占用的内存
常用性能优化方案
创建索引
限定返回结果数
只查询使用到的字段
采用capped collection
采用Server Side Code Execution
使用Hint,强制使用索引
采用Profiling
优化器Profiling(对应MySQL的慢查询日志)
MongoDB Database Profiler
1、开启profiling
两种开启方式,一是启动参数加上 -profile=[级别],二是调用db.setProfilingLevel(级别)。
共有三个级别:0-不开启;1、记录慢命令(默认为>100ms);2、记录所有命令。
两种方式设置慢命令时限,一是启动参数加上 -slowms,而是db.setProfilingLevel加上第二个参数db.setProfilingLevel(level, slowms)。
2、查询profiling记录
Profiler的日志记录在数据库里,位于system.profile,
> db.system.profile.find( { millis : { $gt : 5 } } )// 列出执行时间长于某一限度(5ms)的Profile记录:
> show profile // 列出最近5 条执行时间超过1ms 的 Profile 记录