MongoDB 索引

索引是用来加快查询速度的,事物都有双面性的,同时在每次插入、更新和删除操作时都会产生额外的开销。索引有时并不能解决查询慢的问题,一般来说,返回集合中一半以上的结果,全表扫描要比查询索引更高效些。创建太多索引,会导致插入非常慢,同时还会占用很大空间。可以通过explain和hint工具来分析。mongo 的索引非常强大,和关系型数据库索引没什么区别。MongoDB中索引是大小写敏感的。

查看索引

db.demo.getIndexes();

删除集合所有索引:

> db.collection.dropIndexes()

删除集合某个索引:

> db.collection.dropIndex({x:1})

mongodb使用createIndex方法来创建索引。语法:
db.COLLECTION_NAME.createIndex(keys[,options])

当有大量数据时,创建索引会非常耗时,可以指定到后台执行,只需指定“backgroud:true”即可。

> db.ttlsa_posts.ensureIndex({pid:1},{backgroud:true});

嵌入式索引 为内嵌文档的键创建索引与普通的键创建索引并无差异。

> db.ttlsa_posts.ensureIndex({"post.date":1})

创建唯一索引

我们也可以定义唯一索引,方法就是指定unique键为true,如:

>> db.users.createIndex({email:1},{'unique':true})

当为已有的集合创建索引,可能有些数据已经有重复了的,那么创建唯一索引将失败。可以使用dropDups来保留第一个文档,而后的重复文档将删除,这种方法慎重操作。

> db.ttlsa_posts.ensureIndex({pid:1},{unique:true, dropDups:true})

强制索引 hint命令可以强制使用某个索引

> db.ttlsa_posts.find({pid:{$lt:333}}).hint({pid:1,date:1})

创建部分索引语法:

db.collection.createIndex(keys, options)

options可以使用partialFilterExpression,即部分过滤表达式,其类型为文档类型

过滤表达式通常包括:$exists, $gt, $gte, $lt, $lte,$type,$and

过滤表达式使用示例:

db.persons.createIndex({name:1},{partialFilterExpression:{age: {$gt:25}}})

此句的意思是:基于age列创建大于25岁的部分索引。创建的部分索引过滤条件是age大于25,当查询的条件是country等于china,age大于25。 条件满足,从执行计划里可以看出此次查询采用索引扫描。

文本索引

MongoDB提供文本索引以支持对字符串内容的文本搜索查询。text索引可以包括其值为字符串或字符串元素数组的任何字段。

文本索引,顾名思义就是用于搜索文本的,可以用于搜索所有的value,也可以搜索指定的field对应的value。只要field对应value是string,或者对应的value是array且array中的元素是string,那么文本索引都可以索引该field.注意:一个集合最多只能有一个文本索引。如以下示例所示:

db.collection.createIndex({keys:”text”})

也可以创建多个字段text,例如
db.collection.createIndex({subject:”text”,comments:”text”})

查询

db.collection.find({$text:{$search:”MongoDB best”}})

查询出来的结果集是:

{_id:5908df789dfd1fd5884fd84f7df4,statement:MongoDB is the worst}

{_id:5908dfgfh587hgf15f4hf54hf418,statement:MongoDB is the best}

这是因为文本查询时,每个单词之间的分隔是”或者”,所以上面的查询语句的意思是:查询包含MongoDB或者best的记录数。

通过explain结果来分析性能
我们往往会通过打点数据来分析业务的性能瓶颈,这时,我们会发现很多瓶颈都是出现在数据库相关的操作上,这时由于数据库的查询和存取都涉及大量的IO操作,而且有时由于使用不当,会导致IO操作的大幅度增长,从而导致了产生性能问题。而MongoDB提供了一个explain工具来用于分析数据库的操作。直接拿官网的示例来做说明:

假设我们在inventory collection中有如下文档:

{ "_id" : 1, "item" : "f1", type: "food", quantity: 500 }
{ "_id" : 2, "item" : "f2", type: "food", quantity: 100 }
{ "_id" : 3, "item" : "p1", type: "paper", quantity: 200 }
{ "_id" : 4, "item" : "p2", type: "paper", quantity: 150 }
{ "_id" : 5, "item" : "f3", type: "food", quantity: 300 }
{ "_id" : 6, "item" : "t1", type: "toys", quantity: 500 }
{ "_id" : 7, "item" : "a1", type: "apparel", quantity: 250 }
{ "_id" : 8, "item" : "a2", type: "apparel", quantity: 400 }
{ "_id" : 9, "item" : "t2", type: "toys", quantity: 50 }
{ "_id" : 10, "item" : "f4", type: "food", quantity: 75 }

假设此时没有建立索引,做如下查询:

db.inventory.find( { quantity: { $gte: 100, $lte: 200 } } )

返回结果如下:

{ "_id" : 2, "item" : "f2", "type" : "food", "quantity" : 100 }
{ "_id" : 3, "item" : "p1", "type" : "paper", "quantity" : 200 }
{ "_id" : 4, "item" : "p2", "type" : "paper", "quantity" : 150 }

这是我们可以通过explain来分析整个查询的过程:

# explain 有三种模式: "queryPlanner", "executionStats", and "allPlansExecution".
# 其中最常用的就是第二种"executionStats",它会返回具体执行的时候的统计数据
db.inventory.find(
   { quantity: { $gte: 100, $lte: 200 } }
).explain("executionStats");

查询结果中有一个"stage"字段,而MongoDB总共有如下几种stage:

  • COLLSCAN – 全表扫描
  • IXSCAN – 索引扫描
  • FETCH – Retrieving documents
  • SHARD_MERGE – Merging results from shards
  • SORT – Explicit sort rather than using index order

碰到索引不一致的情况,想从A库中导出索引在B库执行

var collectionList = db.getCollectionNames();
for(var index in collectionList){
	var collection = collectionList[index];
	var cur = db.getCollection(collection).getIndexes();
	if(cur.length == 1){
		continue;
	}
	for(var index1 in cur){
		var next = cur[index1];
		if(next["_id"] == '1'){
			continue;
		}
		print("try{ db.getCollection(\""+collection+"\").ensureIndex("+JSON.stringify(next)+",{background:1})}catch(e){print(e)}");
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值