Index 能够提高查询的性能,如果没有Index,MongoDB必须扫描整个collection,从collection的第一个doc开始,直到最后一个doc,即使第一个doc之后的所有doc都不满足查询条件。如果在Collection上有合适的Index,例如,unique index,那么MongoDB在按照index key查找到一个doc之后,就不会继续对其他doc查询,极大地提高查询性能。

MongoDB的 Index 结构跟关系型DB的NonClustered Index相似,都是BTree结构,在每个leaf node中,除了index key之外,还存储相应doc在disk上的地址。在MongoDB中,没有clustered index,因此,Collection初始的物理存储跟doc插入的顺序有关,MongoDB按照doc插入的顺序,依次将doc存储在disk上,插入顺序上相邻的doc在disk的物理位置上也是相邻的;对doc的修改可能对 collection 的物理存储发生变化,如果doc的修改不会导致doc的size增加,那么doc会继续存储在原来的存储空间中,而不会对collection的物理存储有影响,一旦修改操作导致doc的size增加,导致doc发生移动,那么collection的物理存储就会发生变化。

一,doc的移动影响collection的物理存储

如果数据修改增加了doc的size,使其不能继续存放在原来的存储空间中,那么MongoDB必须将其移动到collection的末尾,原先的存储空间被闲置,导致doc的存储密度下降,会严重影响查询性能。doc的移动过程是非常慢的,相当于在一个原子操作中,先做doc的 delete 操作,后做doc的 insert 操作。

doc移动的过程如下图所示:

对doc B进行修改,使其Size增大,原先的位置不能容纳B,MongoDB将B移动在Collection的末尾。原来的存储空间被闲置。

二,创建index

MongoDB的index是BTree 结构,BTee结构的特点是:查询每个值所要进行查询的次数时固定的,最小的值存储在最左边的叶子节点上,做大的值存储在最右边的叶子节点上,如图:

MongoDB默认按照“_id”字段的升序创建index,最后创建的doc位于index的右侧。如果每次查询时,都是查询最后的N个doc,那么按照"_id"的值倒叙查询,limit 前100,查询性能是十分快速的。也可以手动创建符合业务需要的Index,MongoDB使用 db.collection.createIndex(keys,option)函数创建index。

keys的格式是:{field:1/-1,,},field是doc的字段,1/-1 表示按照field排序的方向创建index:1表示按照field的升序创建,-1表示按照field的降序创建。

db.collection.createIndex(keys,option) 

1,创建示例数据,按照 age 字段升序创建index

创建的Index按照age的升序存储age字段,在叶子节点中,除了age字段,叶子节点还会存储doc的地址(指针),用于定位相应的doc,查询除index key(age)之外的其他字段。下面的语句创建的index name是 age_1。

for(i=0;i<10000;i++)
{
db.foo.insert({"idx":i,name:"user "+1,age:i%90})
} --create index by age ascendant
db.foo.createIndex({age:1})

2,查看查询的query plan

在示例中,由于查询语句中没有设置projection,MongoDB返回doc中的所有fields,由于index:age_1只包含age字段,其他字段必须定位到原doc中获取,因此多一次寻址操作。

db.foo.find({age:22}).explain("executionStats")

在查询语句中设置Projection,只返回age字段,那么index:age_1 就能包含结果集中所有字段,不需要定位到原doc中,不仅提高查询性能,而且减少Disk IO 和内存的使用量,因此,应对每个结果集设置Projection,不要返回"_id"字段等其他不需要的字段。通过搜索index就能获取所有field的index是覆盖索引(convered index),覆盖索引不需要定位到原doc中。

db.foo.find({age:22},{age:1,_id:0}).explain("executionStats")

三,index 和 排序

排序是一个非常耗费内存资源的操作,在MongoDB中,如果排序的中间结果集大小消耗的系统内存超过32MB,MongoDB就会报错,拒绝如此多的数据进行排序。32MB是一个阈值,如果超出值,那么必须使用 index 来获取经过排序的数据集。

MongoDB:When unable to obtain the sort order from an index, MongoDB will sort the results in memory, which requires that the result set being sorted is less than 32 megabytes. When the sort operation consumes more than 32 megabytes, MongoDB returns an error.

通过Index来执行排序操作,要求排序的字段和index key的前缀字段相同,如果满足该条件,那么MongoDB会直接返回顺序的结果集,而不需要执行实际的排序操作。例如,如果index key是{age:1,name:1},如果排序操作是sort({age:1}),或 sort({age:1,name:1}),符合index前缀排序,那么结果集会直接返回,不需要排序;如果排序操作是sort({name:1}),或sort({name:1,age:1}),不符合index前缀排序,结果集还是需要在内存中进行排序,如果内存消耗超过32MB,MongoDB报错。

示例,符合前缀排序的Index 和 sort 操作

 db.foo.find({age:22}).sort({age:1})

由于MongoDB通过Index来执行排序操作,并且MongoDB对排序操作消耗的内存资源有严格限制,因此,在创建index,应在查找和排序之间做折衷,在满足排序操作的前提下,使查询性能更高。在创建index时,使用 {"Sort Key":1, "query filter":1} 格式是非常有用。

四,对内嵌doc进行索引

MongoDB index的强大之处在于能够在内嵌doc的字段上创建index,创建的语法和普通doc一致,在引用内嵌doc中的字段时,使用dot notation,可以对任意深度的内嵌doc字段建立index。

例如,doc结构如下,contact是内嵌doc,按照 contact.phone 字段升序创建索引。

{
name:"u1",
age:22,
contact:
{
phone:123
email:"xx@163.com"
}
} --create index
db.foo.createIndex({"contact.phone":1})

五,Index 维护

1,查看在collection上创建的index

使用db.collectionName.getIndexes() 查看给定collection上的所有index信息:

  • key是指index key的定义,包括两部分:key 和排序的方向;
  • name是index name;
  • ns是namespace;
  • v 标识index 版本,如果索引中包含"v":1,说明index是以新格式存储的,性能较高。
db.collection.getIndexes()

2,删除index

db.collection.dropIndex(index)

方式一,按照index name 删除index

db.foo.dropIndex("age_1")

方式二,按照Index key删除index

db.foo.dropIndex({age:1})

3,重建collection中的所有index

db.collection.reIndex()

The db.collection.reIndex() drops all indexes on a collection and recreates them. This operation may be expensive for collections that have a large amount of data and/or a large number of indexes.

参考doc:

MongoDB CRUD Concepts

cursor.explain()

Indexes

MongoDB 使用Index的更多相关文章

  1. mongodb(Index)

    备忘mongoDb 索引的一些知识点. 1.索引是用以加速数据库查询的手段,在mongo中主要是采用B树的方式: 2.每个集合最多可增加64个索引,不建议增加过多索引,原因在于一是索引本身占用空间,二 ...

  2. mongodb query index 分析

    query 的过程及分析: query 是通过Query planner选择最有效的查询plan ,为一个query 被给予一个可用的索引,查询时 query optimizer(最优的查询条件选择器 ...

  3. MongoDB collection Index DB 大小查询

    1.collection中的数据大小 db.collection.dataSize() 2.为collection分配的空间大小,包括未使用的空间db.collection.storageSize() ...

  4. mongodb AND查询遇到多个index时候可能会做交集——和复合索引不同

    关于MongoDB中索引文档的一个问题? - To illustrate index intersection, consider a collection orders that has the f ...

  5. MongoDB之TextSearch简介

    MongoDB之TextSearch简介  MongoDB支持对文本内容执行文本搜索操作,其提供了索引text index和查询操作$text来完成文本搜索功能.下面我们通过一个简单的例子来体验一下M ...

  6. spring data mongodb中,如果对象中的属性不想加入到数据库字段中

    spring data mongodb中,如果对象中的属性不想加入到数据库字段中,可加@Transient注解,声明为透明属性 spring data mongodb 官网帮助文档 http://ww ...

  7. mongodb地理位置索引

    初始化集合(经度在前,纬度在后) ? 1 2 3 mongos> db.checkins.insert({ "_id" : "101", "lo ...

  8. Spring boot中使用Mongodb

    安装 使用Idea新建Spring boot工程时需要选择Mongodb 或者在工程中加入依赖 Maven: <dependency> <groupId>org.springf ...

  9. mongodb 数组查询

    转发自:https://blog.csdn.net/leshami/article/details/55049891 一.演示环境及数据> db.version() 3.2.11 > db ...

随机推荐

  1. 接口测试SoapUI参数化

    上次和大家一起完成了soapui的参数之一properties,今天我们一起交流另外一种参数化的方法,跟着一起练习,不懂不要紧,练习多了就会慢慢懂的: 1.准备excle(目前soapui只支持xls ...

  2. 不使用return false阻止event默认行为

    当我们点击一个a标签时,如果这个标签的href指向了另一个地址,那么浏览器会默认跳转到此地址.在页面中,有时我们需要触发点击事件,但是又不想触发默认行为,就需要阻止event的默认行为了. 常规做法 ...

  3. MySql UDF 调用外部程序和系统命令

    1.mysql利用mysqludf的一个mysql插件可以实现调用外部程序和系统命令 下载lib_mysqludf_sys程序:https://github.com/mysqludf/lib_mysq ...

  4. 关于MVC的开源商城 Nop之闲聊

    nopcommerce是国外的一个高质量的开源b2c网站系统,基于EntityFramework4.0和MVC3.0,使用Razor模板引擎,有很强的插件机制,包括支付配送功能都是通过插件来实现的,基 ...

  5. swiper的初步使用

    1.引入文件,顺序引入(此处基于jquery,且版本至少1.7以上) <link rel="stylesheet" href="path/to/swiper-3.4 ...

  6. PMP备考_第五章_项目范围管理_实践思考

    项目范围管理 前言 今天学习项目范围管理的内容,深切的感受到了原单位在项目管理方面存在的问题,今天在这里做一个总结,既相当于对项目范围的一个学习整理,也相当于自己对项目实践过程中存在问题的一个思考. ...

  7. linux安装VMware-tools,

    系统中可能预装了open-vm-tools和VMware-tools冲突,所以需要先将前者卸载在进行安装不同系统卸载使用的命令不一样,centos的命令可以使用rpm,ubuntu的命令可以使用dpk ...

  8. 让IE6/IE7/IE8浏览器支持CSS3属性

    让IE6/IE7/IE8浏览器支持CSS3属性 一.下载 您可以狠狠地点击这里:ie-css3.htc,这个玩意儿是让IE浏览器支持CSS3表现的关键东东. 二.上面的是什么东西 首先说说.htc文件 ...

  9. java之数据结构之链表及包装类、包

    链表是java中的一种常见的基础数据结构,是一种线性表,但是不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针.与线性对应的一种算法是递归算法:递归算法是一种直接或间接的调用自身算法的过 ...

  10. ASP.NET Core Kestrel 中使用 HTTPS (SSL)

    在ASP.NET Core中,如果在Kestrel中想使用HTTPS对站点进行加密传输,可以按照如下方式 申请证书 这一步就不详细说了,有免费的和收费的,申请完成之后会给你一个*.pfx结尾的文件. ...