传统的结构化的数据:固定长度,固定的类型 linux
非结构化的数据:doc,ppt,pdf.c++
nosql(不只仅是数据库能够干的事情),指的是非关系型数据库,以键值对存储,它的结构不固定,没一条记录能够有不同的键,每条记录能够根据须要增长一些本身的键值对,这样就不会局限于固定的结构,能够减小一些时间和空间的开销。web
常见的有:CouchDB、Redis、MongoDB、Neo4j、HBase、BigTablesql
是用c++写的非关系型数据库,特色是高性能、易部署、易使用,存储数据很是方便,面向集合存储,易于存储对象类型的数据,模式自由,支持动态查询,支持彻底索引,包含内部对象,支持复制和故障恢复,使用高效的二进制数据存储,包括大型对象,文件存储格式为BSON(一种json的扩展)。mongodb
这里服务器用ubuntu15.10,在secureCRT中链接这个ubuntu。 首先使用 rz 上传window中从官网(https://www.mongodb.com/)下载的mongodb安装文件。数据库
解压这个文件:json
tar -xvzf mongodb-linux-x86_64-ubuntu1404-3.2.7.tgz
//重命名ubuntu
mv mongodb-linux-x86_64-ubuntu1404-3.2.7 mongodb3.2
在目录中新建data,log和conf文件夹,在cong中新建mongodb.config,内容以下:数组
port=27017 dbpath=data logpath=log/mongod.log fork=true
启动服务:浏览器
./bin/mongod -f conf/mongodb.config
链接: mongo客户端链接
bin/mongo 192.168.44.131:27017/test
在linux中链接成功:
网页端:能够在浏览器中查看一下:http://www.192.168.44.131:27017/
关闭:
db.shutdownServer();
查看端口号: ps -ef|grep mongod|grep 27017
kill 相应端口
安装过程与linux基本相同,就是配置一下环境变量,建立data,log,conf目录等。
若是是在window中,启动成功会是这样:
浏览器中访问:http://www.localhost:28017/
在mongodb有的版本中会提示端口号加1000的,因此我终于演示的时候是28017端口。
安全性从高到低: 物理隔离、网络隔离、防火墙隔离、用户名密码。
开启权限认证: 在配置文件中——mongodb.config中设置:
auth=true
建立用户:(2.6以前是addUser)
createUser{user:"
例如:建立用户名为zp,密码为a的用户
db.createUser({user:"zp",pwd:"a",roles:[{role:"userAdmin",db:"admin"},{role:"read",db:"test"}]})
登录:
bin/mongod 192.168.44.131 -u zp -p a
数据库角色 :read, readWrite,dbAdmin, dbOwner, userAdmin
集群角色:clusterAdmin,clusterManager
备份角色:backup,restore
其余:DBAdminAnyDatabase
//查看数据库
show dbs
//查看表
show tables
//建立数据库
use one_db
//插入数据 格式:db.表名.insert({ json格式的数据 }) 例如:
db.one_db_collection.insert({ x:1 })
//查询刚才写入的表
show collections
查询具体内容 db.onedbcollection.find()
运行结果为:
{ "_id" : ObjectId("576fdc6e8224cdb105bcb3df"), "x" : 1 }
id是系统自动生成的,每条数据的id是惟一的 咱们还能够本身给_id赋值:
db.one_db_collection.insert({x:2,_id:1})
批量插入多条数据
for(i=4;i<20;i++)db.one_db_collection.insert({x:i})
统计条数:
db.one_db_collection.find().count()
过滤排序:
db.one_db_collection.find().skip(5).limit(3).sort({x:1})
从x:1开始,过滤前5条数据,而后从第6条开始选取3条数据,并进行排序。
演示效果以下:
//更新数据
db.one_db_collection.update({x:1},{x:100})
当插入这样的一条数据的时候:
db.one_db_collection.insert({x:100,y:100,z:100})
这个时候更新y的值,须要加$set符号:
db.one_db_collection.update({z:100},{$set:{y:200}})
当更新一条不存在的数据的时候,若是加上true则会自动建立一条这个不存在的数据
db.one_db_collection.update({y:100},{y:300},true)
效果以下:
//一次性更新多条相同的数据
db.one_db_collection.update({ y:300},{$set:{y:301}},false,true)
若是有多条重名的且update时未加true,则只删除相同数据中的第一条数据。
//数据的删除
db.one_db_collection.remove({y:301})
//删除表
db.one_db_collection.drop()
//查看当前表中索引
db.one_db_collection.getIndexes()
//建立索引
db.one_db_collection.ensureIndex({x:1})
x:1表明正向排序,x:-1表明逆向排序。若是文档数目较大,则建立索引时间会较长。若是系统中已经有不少文档了,这个时候就不能使用这个命令去建立索引了,不然严重影响数据库性能。 咱们通常须要在使用数据库以前就要把索引建立完毕。 使用索引能够明显加快查询速度。
索引的属性 :
名字,由name指定;惟一性,unique指定;稀疏性,sparse指定
db.collection.ensureIndex({},{name:""}) db.collection.ensureIndex({},{unique:true/false}) db.collection.ensureIndex({},{sparse:true/false})
—id索引:是绝大多数集合默认创建的索引,对于每一个插入的数据,MongoDB都会自动生成一条惟一的id字段。
db.one_db_collection.ensureIndex({x:1})
例如查询结果为: { "_id" : ObjectId("576fecca8224cdb105bcb3f1"), "x" : 1 }
多键索引: 1.多键索引与单键索引建立形式相同,区别在于字段的值。 1)单键索引:值为一个单一的值,如字符串,数字或日期。 2)多键索引:值具备多个记录,如数组。
db.twodb.insert({x:[1,2,3,4,5]})
复合索引:
db.twodb.ensureIndex({x:1,y:1})
过时索引: 此索引过一段时间会过时,索引过时后,相应的数据会被删除,适合存储一些在一段时间以后会失效的数据,好比用户登陆信息.
db.twodb.ensureIndex({time:1},{expireAfterSeconds:60}) //过时时间设置为60秒 db.twodb.insert({time:new Date()}) db.twodb.find() //60秒后就查不到数据了
过时索引的限制: 1.存储在过时索引字段的值必须是指定的时间类型,必须是ISODate或者ISODate数组,不能使用时间戳,不然不能自动删除。 例如 >db.twodb.insert({time:1}),这种是不能被自动删除的 2.若是指定了ISODate数组,则按照最小的时间进行删除。 3.过时索引不能是复合索引。由于不能指定两个过时时间。 4.删除时间是不精确的。删除过程是由MongoDB的后台进程每60s跑一次的,并且删除也须要必定时间,因此存在偏差。
对字符串与字符串数组建立全文可搜索的索引
建立全文索引的方法
db.threedb.ensureIndex({key:"text"}) db.threedb.ensureIndex({key_1:"text",key_2:"text"}) db.threedb.ensureIndex({"$**":"text"})
演示建立一个全文索引
db.threedb.ensureIndex({"article":"text"})
插入几条演示数据
db.threedb.insert({"article":"aa bb cc dd ee 11"}) db.threedb.insert({"article":"aa dd rr jj ff 22"}) db.threedb.insert({"article":"aa oo qq tt kk 33"})
使用全文索引进行查询 //搜索标题中有aa的记录
db.threedb.find({$text:{$search:"aa"}})
//多个关键字查找,查找只要含有dd qq 33中任何一个的就能够("或"关系)
db.threedb.find({$text:{$search:"dd qq 33"}})
//查找包含dd qq可是不包含33的数据,在关键词前面加上-号表明不包含:
db.threedb.find({$text:{$search:"dd qq -33"}})
//"与"关系查找,既包含aa 又包含qq的数据
db.threedb.find({$text:{$search:"\"aa\" \"qq\" "}})
//类似度查询
使用$meta:{score:{$meta:"textScore"}} 写在查询条件后面能够返回结果的类似度,与sort一块儿使用,能够达到很好的实用效果。
db.threedb.find({$text:{$search:"dd qq 33"}},{score:{$meta:"textScore"}})
db.threedb.find({$text:{$search:"dd qq 33"}},{score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}})
全文搜索的使用限制
将一些点的位置存储在Mongodb数据库中,而且建立索引,这些就是地理位置索引,以后就能够按照位置来查找其余的点了!
分类 1.2D索引,用于存储和查找平面上的点。 2.2Dsphere索引,用于存储和查找球面上的点。
查找方式: 1:查找距离某个点必定距离内的点 2:查找包含在某个区域内的点
2D地理位置索引建立方式 db.collection.ensureIndex({w:"2d"}) 2D地理位置索引的取值范围以及表示方法 经纬度[经度,纬度] 经纬度取值范围 经度[-180,180] 纬度[-90,90]
//建立2d索引
db.location.ensureIndex({"w":"2d"})
//插入数据 db.location.insert({w:[20,30]}) db.location.insert({w:[160,90]}) db.location.insert({w:[20,90]}) db.location.insert({w:[80,120]})
一、使用$near 查询距离某个点最近的点 db.collection.find({w:{$near:[x,y]}}) 使用$near默认返回最近的100个点,可使用$maxDistance:x 限制返回的最远距离 查询距离(1,1)最近的点
db.location.find({w:{$near:[1,1]}})
查询在最远距离为100的点
db.location.find({w:{$near:[1,1],$maxDistance:100}})
二、使用$geoWithin 查询某个形状内的点 形状的表示方式: 1. $box 矩形,使用{$box:[[x1,y1],[x2,y2]]} 2. $center 圆形,使用 {$center:[[x,y],r]} 3. $polygon 多边形,使用 {$polygon:[[x1,y1],[x2,y2],[x3,y3]]}
//查询在(0,0)(80,80)之间的位置的数据 一个矩形
db.location.find({w:{$geoWithin:{$box:[[0,0],[80,80]]}}})
//圆形区域内,原心为(20,30),半径是80
db.location.find({w:{$geoWithin:{$center:[[20,30],80]}}})
//多边形
db.location.find({w:{$geoWithin:{$polygon:[[0,0],[40,30],[80,100],[30,60]]}}})
//geoNear的使用 格式: db.runCommand({geoNear:
查询距离(1,1)最远距离为100的,最多返回1条数据
db.runCommand({geoNear:"location",near:[1,1],maxDistance:100,num:1})
2dsphere索引
GeoJSON:描述一个点,一条直线,多边形等形状。 格式: {type:'', coordinates:[list]} GeoJSON查询可支持多边形交叉点等,支持MaxDistance 和 MinDistance
db.collection.ensureindex({key: '2dsphere'})
如何评判当前索引构建状况: 1.mongostat 工具
使用mongostat -h [ip]:端口 例如:
bin/mongostat -h 192.168.44.131:27017
idx miss和qr|qw是须要咱们重点关注的地方。
2.profile集合
db.getProfilingStatus() db.getProfilingLevel()
当level为0表明profiling是关闭的. 级别为1时会记录全部超过slowms中设定的数目的操做。 级别为2时会记录你的全部操做。
3.日志分析
在配置文件中——mongodb.config中设置:
verbose=VVVVV
设置日志,5个v记录最详细的数据,1个v记录简单的日志信息。1到5个v来进行设置。
4.使用explain查询分析器分析
db.collection.find({x:1}).explain()
{ "cursor" : "BasicCursor", --使用的游标 "isMultiKey" : false, "n" : 1, "nscannedObjects" : 100000, --扫描的数据量 "nscanned" : 100000, --包含索引的扫描量 "nscannedObjectsAllPlans" : 100000, "nscannedAllPlans" : 100000, "scanAndOrder" : false, "indexOnly" : false, "nYields" : 781, "nChunkSkips" : 0, "millis" : 25, --查询消耗时间(毫秒) "server" : "XXX", "filterSet" : false }
1:为何有这么多种索引?
不一样的状况下使用对应状况下的索引,可让查询速度更快,可使查询获得进一步的优化。
2:何时使用什么索引才是合适的?
简单的说,索引就比如一本书的目录,你只要浏览标题就能够快速的找到具体内容是放在哪一页的。也就是说用find()查找时不用直接去搜索表,只要查找索引,就能够直接定位到你想查找的内容位置。索引带来的方便不是免费的,是以每次插入或更新(至关于删除并插入)时都要维护索引为代价的。因此若是一张表更可能是用于查询而不多插入,那么就能够创建尽可能多的索引以优化查询性能。相反若是一张表要常常插入或更新,则尽量少用索引,有时甚至连主键都不建。
3:怎么判断索引创建的合适与否?
索引的创建必须慎重,对每一个索引的必要性都应该通过仔细分析,要有创建的依据.由于太多的索引与不充分、不正确的索引对性能都毫无益处:在表上创建的每一个索引都会增长存储开销,索引对于插入、删除、更新操做也会增长处理上的开销.另外,过多的复合索引,在有单字段索引的状况下,通常都是没有存在价值的;相反,还会下降数据增长删除时的性能,特别是对频繁更新的表来讲,负面影响更大.