走进MongoDB(三)基本索引操作

2016-11-08 - 1,519 Views - 0 Goods - Nothing

从根本上说,MongoDB中的索引与其他数据库的索引类似。

我们全文用一个案例为例子,来讲述MongoDB的索引。
首先,我们创建10w数据的文档。


for(var i=0; i<100000; i++){
    db.index_temo.insert({
    "tech_name":"mongodb"+i,"remark":"mongodb remark..."+i
   })
}

我们再查看下插入的文档数


db.index_temo.count()

现在,我们在查看下查询效率


db.index_temo.find({"tech_name":"mongodb1"}).explain("executionStats");

查询结果


"executionStages" : {
"stage" : "COLLSCAN", // 扫描方式: 全表扫描
"filter" : {
"tech_name" : {
"$eq" : "mongodb1"
}
},
"nReturned" : 1, //最终返回了1个文档
"executionTimeMillisEstimate" : 50, //耗时50毫秒
"works" : 100002,
"advanced" : 1,
"needTime" : 100000, //数据库浏览了10w个文档
"needFetch" : 0,
"saveState" : 781,
"restoreState" : 781,
"isEOF" : 1,
"invalidates" : 0,
"direction" : "forward",
"docsExamined" : 100000
}

索引查询

在维护过程中,我们可能希望检查某个索引是否还存在。集合中的每个索引在 system.indexes 集合中都存有一份相对应的 document ,然后您可以使用标准查询使用 getIndexes() 方法返回集合的索引列表。
结合上面的例子,我们来查询下索引


db.index_temo.getIndexes();

查询结果如下


[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "index_demo.index_temo"
}
]

值得说明的是,MongoDB文档会有一个默认的“_id”字段索引。

索引创建

MongoDB提供了几个只会影响索引创建的选项。您可以在使用 db.collection.createIndex() 时,把这些选项设置在一个文档里传递给方法作为第二个参数。从mongoDB 3.0开始ensureIndex被废弃,今后都仅仅是db.collection.createIndex的一个别名。

创建单键索引

我们现在创建一个单键索引


db.index_temo.createIndex( { tech_name: 1 } )

在索引明细中键的值描述了这个键的索引类型。例如,值 1 表明这个索引会将它的索引项按照升序排序。值-1 表明索引会按照降序排布索引项。

创建复合索引

有时候我们的查询不是单条件的,可能是多条件的。那么,这个时候我们可以创建复合索引。


db.index_temo.createIndex( { tech_name: 1 ,remark:1} )

与单键索引类似,在索引明细中键的值描述了这个键的索引类型。例如,值 1 表明这个索引会将它的索引项按照升序排序。值-1 表明索引会按照降序排布索引项。

创建唯一索引

MongoDB允许对一个索引指定唯一性限制。这个限制会阻止应用插入被索引键上的值是重复值的 documents 。此外,如果您希望在已经存储了数据并且被索引键的值有可能重复的集合上创建索引,那么您可以选择将唯一性和删除重复选项组合使用。


db.index_temo.createIndex( { tech_name: 1 }, { unique: true } )

索引 _id 索引 就是一个唯一索引。在某些情况下您可以考虑使用 _id 键的值本身作为这类唯一数据,而不需要在其他键上创建一个唯一索引。

创建过期索引

过期索引是一种特殊索引,通过这种索引MongoDB会过一段时间后自动移除集合中的文档。这对于某些类型的信息来说是一个很理想的特性,例如机器生成的事件数据,日志,会话信息等,这些数据都只需要在数据库中保存有限时间。


db.index_temo.createIndex( { tech_name: 1 }, { expireAfterSeconds: 3600 } )

值得注意的是,删除时间是不精确的。删除过程中,后台程序定时跑一次,而且删除也需要一些时间,所以存在误差。此外,过期索引不能是复合索引,而且存在在过期索引的字段必须是指定的时间类型,必须是ISODate或者ISODate数组,不能是时间戳,否则不能自动删除。

后台创建索引

默认情况下,创建索引会阻塞数据库中所有其他操作。当在一个集合上创建索引时,存储了这个集合的数据库变成不可读不可写的状态知道索引建立完毕。任何需要所有数据库中读或者写锁的操作将会等待,直到后台索引创建完成。

默认情况下,创建索引会阻塞数据库中所有其他操作。当在一个集合上创建索引时,存储了这个集合的数据库变成不可读不可写的状态知道索引建立完毕。任何需要所有数据库中读或者写锁的操作(将会等待,直到后台索引创建完成。
对于可能需要长时间运行的索引创建操作,可以考虑 background 选项,这样MongoDB数据库在索引创建期间仍然是可用的。例如,创建一个索引,这个过程在后台运行,可以使用如下方式:


db.index_temo.createIndex({background: true} )

默认MongoDB索引创建的 background 是 false 。

后台索引创建操作使用的是一种增量的方式,这会比普通的 “前台” 创建过程慢。如果索引大于现有的内存,那么这个增量处理过程将会比前台创建过程久得多。如果您的应用中包含 ensureIndex() 操作,且出于其他操作上的考虑这个索引不存在,那么建立一个索引可能会对数据库的性能有严重影响。为了避免性能问题,请确保您的应用在启动时就使用 getIndexes() 方法检查索引是否存在,如果不存在请退出应用。或者在生产实例上使用不同的应用代码在指定的维护时间窗口期间创建索引。

删除索引

如果希望从集合中删除索引,使用 dropIndex() 方法。


db.index_temo.dropIndex("tech_name_1")
转载请注明原文链接:首页 -> 技术交流 -> 走进MongoDB(三)基本索引操作
  • 支付宝打赏
  • 微信打赏

China.BeiJing

如果说人生是自我编写的程序,那么青春就是其中意味深长的代码