(一)索引的种类
- _id 索引
- 单键索引
- 多键索引
- 复合索引
- 过期索引
- 全文索引
- 地理位置索引
(二)查询索引
1、查询集合中所有索引
db.imooc_collection.getIndexes()
(三)索引属性
1、创建索引时的格式:db.collection.ensureIndex({param},{param}),第2个参数便是对应的属性。
2、比较重要的属性:
(1)名字,name指定:
db.collection.ensureIndex({},{name;” “})
一旦我们自定义 name 之后,我们在删除索引是,可将自定义 name 作为参数
db.collection.dropIndex(“name”)
(2)唯一性,unique指定,利用unique可以实现若存在,则不插入,若不存在则插入。
db.collection.ensureIndex({},{unique:true/false})
(3)稀疏性,sparse指定,不必为不存在的字段创建索引(默认不稀疏)
db.collection.ensureIndex({},{sparse:true/false})
#查找存在 m 字段的数据
①db.imooc_2.find({m:{$exists:true}})
#建立 m 字段索引,且指定 稀疏性 true
②db.imooc_2.ensureIndex({m:1},{sparse:true})
#查找非 m 字段的数据
③db.imooc_2.find(m:{$exists:false})
如果mongoDB在选取索引时,如果发现在稀疏索引上查找不存在文档,将不会使用稀疏索引,如果强制指定的话,就会发现问题。
④db.imooc_2.getIndexs()
⑤db.imooc_2.find({m:{$exists:false}}).hint(“m_1”)
不能在稀疏索引上查找字段不存在的记录。
(4)是否定时删除,expireAfterSeconds指定:TTL,过期索引。
(四)创建索引
1、_id 索引
自动创建,无需手动创建
2、单键索引
db.imooc_collection.ensureIndex({x:1})
(1)ensureIndex创建索引,参数是json文档
(2)key的值不再代表值,而是代表方向: x:1代表正向排序,x:-1代表逆向排序。
(3)创建索引要消耗很长的时间,如果系统负载较重,且有很多已经存在的文档,则不能直接使用ensureIndex这个命令,需要在数据库创建之前就创建索引。
(4)创建索引会对写入有一定的影响
3、多键索引
db.imooc_collection.insert({x:[1,2,3,4,5]})
解析:因为上面在创建单键索引时,就是在 x 上创建的,所以,当这里插入的数据为数组时,就自动变为了多键索引。
4、复合索引
插入数据
db.imooc_collection.insert({x:1,y:2,z:3})
创建复合索引
db.imooc_collection.ensureIndex({x:1,y:1})
1代表正向排序 -1代表逆向排序
5、过期索引
创建过期索引
db.imooc_collection.ensureIndex({time:1},{expireAfterSeconds:10})
插入数据
db.imooc_collection.insert({time:new Date()})
解析:{expireAfterSeconds:10} 过期时间 10s
过期索引的限制:
1.存储在过期索引字段的值必须是指定的时间类型,必须是ISODate或者ISODate数组,不能使用时间戳,否则不能自动删除。
例如 >db.imooc_collection.insert({time:1}),这种是不能被自动删除的
2.如果指定了ISODate数组,则按照最小的时间进行删除。
3.过期索引不能是复合索引。因为不能指定两个过期时间。
4.删除时间是不精确的。删除过程是由MongoDB的后台进程每60s跑一次的,而且删除也需要一定时间,所以存在误差。
6、全文索引
(1)创建全文索引
1、db.imooc_collection.ensuerIndex({key:“text”})
为key字段建全文索引,text为参数。
2、db.imooc_collection.ensuerIndex({key_1:“text”,key_2:“text”})
为key_1,key_2字段建全文索引,text为参数。
3、db.imooc_collection.ensuerIndex({"$**":“text”})
不指定字段,创建集合下所有信息的全文索引。
(2)使用全文索引查询
注意:一个集合只能创建一个全文索引
#查询包含aa的内容的文档
db.imooc_collection.find({$text:{$search:"aa"}})
#(或查询)查询包含aa或bb或cc的内容的文档
db.imooc_collection.find({$text:{$search:"aa bb cc"}})
#(\ 与查询)查询包含aa、bb和cc的内容的文档
db.imooc_collection.find({$text:{$search:"\"aa\" \"bb\" \"cc\""}})
# -为排除包含有cc内容的文档
db.imooc_collection.find({$text:{$search:"aa bb -cc"}})
(3)使用全文索引带权重查询
参数{score:{$meta:“textScore”}},用于标识相似度。
#参数{score:{$meta:"textScore"}},用于标识相似度。
db.imooc_collection.find({$text:{$search:"aa bb"}},{score:{$meta:"textScore"}})
#按相似度排序
db.imooc_2.find({$text:{$search:"aa bb"}},{score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}})
(4)缺陷
全局索引的限制:
- 每次查询,只能指定一个
$text
查询 $text
查询不能出现在$nor
查询中- 查询中如果包含了
$text
,hint
不再起作用
7、地理位置索引
(1)2d索引
db.collection.ensureIndex({“w”:“2d”})
位置表示方式:经纬度【经度,维度】
取值范围:经度【-180,180】纬度【-90,90】
例如:db.collection.insert({w:[180,90]})
查询方式:
1、$near
查询:查询距离某个点最近的点,默认返回100个最近的点
#查询距离点 [1,1] 最近的点
db.collection.find({w:{$near:[1,1]}})
#查询距离点 [1,1] 最近的点,且距离不超过10
db.collection.find({w:{$near:[1,1],$maxDistance:10}})
2、$geoWithin
查询:查询某个形状内的点
形状的表示
a、$box
:矩形,使用
{$box:[[<x1>,<y1>],[<x2>,<y2>]]}
//第一个坐标代表左边界,第二个右边界
案例:db.location.find({w:{$geoWithin:{$box:[[0,0],[3,3]]}}})
b、$center
:圆形
{$center:[[<x1>,<y1>],r]}
//r为圆的半径
案例:db.location.find({w:{$geoWithin:{$center:[[0,0],3]}}})
c、$polygon
:多边形
{$polygon:[[<x1>,<y1>],[<x2>,<y2>],[<x3>,<y3>]]}
案例:db.location.find({w:{$geoWithin:{$polygon:[[0,0],[0,1],[2,5]]}}})
3、geoNear 查询(可以看做是$near查询的进化版本)
它不仅支持 minDistance,而且它的返回结果多了一些数据。
使用runCommand命令进行使用:
db.runCommand({
getNear:<collection>, //指定数据集合
near:[x,y], //查询坐标
minDistance: (对2d索引无效,对2dsphere有效)
maxDistance: //返回符合文档最多的数量
num:2 //返回的数量
})
4、查询返回结果
{
"results":[ //查询的结果
{
"dis": //查找到的数据与所指定查找的数据之间的距离
"obj":{} //查找到的数据
}
],
"stats":{ //查询的参数
"nscanned": //扫描了哪些数据
"objectsloaded":
"avgDistance": //平均距离
"maxDistance": //最大的距离
"time": //花费的时间
},
"ok":
}
(2)2dsphere 索引
创建方法:db.collection.ensureindex({w: “2dsphere”})
2Dsphere位置表示方式:
GeoJSON:描述一个点,一条直线,多边形等形状。
格式:
{type:’’, coordinates:[list]}
GeoJSON查询可支持多边形交叉点等,支持MaxDistance 和 MinDistance
(五)索引构建情况分析
1、使用索引的优缺点:
优点,加快索引相关的查询
缺点,增加磁盘空间的消耗,降低写入性能
2、判断当前索引构建的情况:
- Mongostat工具
- profile集合
- 日志
- explain
3、Mongostat工具
使用 mongostat 工具:./mongostat -h 127.0.0.1:27017
mongostat 输出部分字段的含义:
(1)inserts/query/update/delete: 分别指当前mongodb插入、查询、更新、删除 数量,以每秒计;
(2)getmore: MongoDB返回结果时,每次只会返回一定量;当我们继续用find()查询更多数据时,系统就会自动用getmore来获取之后的数据;
(3)command: 执行的命令数量;
(4)flushes: MongoDB使用虚拟内存映射的方式管理数据,我们在向MongoDB写入或查询数据时,MongoDB会做一次虚拟内存映射,有些数据其实是在硬盘上的;每隔一段时间,MongoDB会把我们写到内存的数据flush到硬盘上;这个数据大的话,会导致mongodb的性能较差;
(5)mapped/vsize/res: 与磁盘空间大小有关,申请的内存大小;
(6)faults:如果我们查询的数据,没有提前被MongoDB加载到内存中,我们就必须到硬盘上读取,叫做“换页”;如果faults比较高,也会造成性能下降;
(7)idx miss: 表示我们的查询没有命中索引的比率;如果很高,说明索引构建有问题,索引不合适或者索引数量不够;
(8)qr|qw: 说明MongoDB的写队列或者读队列的情况。我们向MongoDB读写时,这些请求会被放到队列中等待。数量大(几百上千)说明MongoDB处理速度慢或者读写请求太多,性能会下降。
(9)ar|aw: 当前活跃的读写客户端的个数。
4、profile集合