`

MongoDB 索引(Index)

阅读更多

一、索引的CRUD

创建索引:ensureIndex()

    db.collection.ensureIndex({"name":1})    为collection的name属性创建正序索引

    db.collection.ensureIndex({"name":1},{unique:true})    为collection的name属性创建正序唯一索引。

     db.collection.ensureIndex({"name":1},{unique:true,dropDups:true})   为collection的name属性创建正序唯一索引。剔除为唯一重复值(在建唯一索引前已经存在重复值)。

 

查看索引:getIndexes()

   db.system.indexes.find()  查看当前数据库的所有索引。 所有数据库都存在索引文档system.indexes

   db.system.namespaces.find() 查看当前数据库的所有索引。

   db.collection.getIndexes()  查询当前数据库中指定collection的索引。

删除索引:dropIndex()

   db.collection.dropIndex({"name":1})    删除collection中的name属性的索引。

   db.collection.dropIndex("name_1")      删除collection中索引名称为name_1的索引

   db.runCommand({dropIndexes:"collection",index:"indexName"})   删除当前数据库中collection文档的索引名称为indexName的索引。注意indexName是索引名称,不是文档的属性名称。

    db.runCommand({dropIndexes:"collection",index:"*"}) 删除当前数据库中collection文档的所有索引。

查询时指定索引:

  Hint 

     eg:db.user.find({name:'张三',sex:'男'}).hint({name:1});   #指定索引key

             db.user.find({name:'张三',sex:'男'}).hint("name_1");     #指定索引名称

     注意:查询时指定索引时指定索引必须存在。

     db.collection.getIndexes();  查询指定集合的索引列表

 

重建索引 reindex()

语法:db.collection.reIndex()

适用场景:一个表经过大量的修改后会导致表的文件上产生空洞,索引文件也是一样,

可以通过重建索引来提高索引的效率。

不好的地方:对于数据量大或者索引多的表来说,重建索引代价重大。

 

一般不需要重建索引,只有集合大小发生显巨变化或磁盘空间占用不成比例时才需要

 

二、索引的分类

   1、默认索引

 

    2、单列索引

 

    3、组合索引

 db.collection.ensureIndex({"provinceId":1,"isDied":1});

 

  注意:组合索引支持的索引查询只是索引的任意前缀索引字段。 

eg:

建表:

db.products.insert({

"_id": ObjectId("56c448bb4b3a77a13d33d5d6"),

"item": "Banana",

"category": ["food", "produce", "grocery"],

"location": "4th Street Store",

"stock": 4,

"type": "cases"

});

 新建索引:db.products.ensureIndex({"item":1,"location": 1,"stock": 1})

 

以下三个查询都不能使用索引:

db.products.find({"location":"4th Street Store"}).explain();

db.products.find({"stock":4}).explain();

db.products.find({"location":"4th Street Store","stock":4}).explain();

下面查询文档上说不能使用索引,但是实际可以使用,不知道为什么 20170220。

db.products.find({"item": "Banana","stock": 4}).explain();

MongoDB 支持索引的前缀查询。

 

    4、内嵌索引

     a,内嵌字段索引(Index on an Embedded Field)

#创建数据
db.records.insert({
  "_id": ObjectId("570c04a4ad233577f97dc459"),
  "score": 1034,
  "location": { state: "NY", city: "New York" }
})

 

#创建索引
db.records.createIndex( { "location.state": 1 } )

 

   

#使用索引查询
    #使用了索引    查询到了数据
    db.records.find( { "location.state": "NY" } ).explain();  
    #使用了索引   查询到了数据
    db.records.find( {"location.city": "New York","location.state": "NY" } ).explain();  
    #使用了索引   查询不到数据
    db.records.find( { location: { city: "New York", state: "NY" } } );

 

   b,内嵌文档索引(Index on an Embedded Documents)

   

#创建数据
db.user.insert(
    {
      name: {
              first: "Yukihiro",
              last: "Matsumoto"
            }
    }
);

db.user.insert(  
    {  
      name: {  
              first: "Yukihiro",  
              last: "Matsumoto",
              center:"center"
            }  
    }  
)

 

#创建索引
db.user.createIndex( { "name": 1 } );

 

#使用索引查询
#使用了索引    查询到了数据(第一条数据)
db.user.find( { name: { first: "Yukihiro", last: "Matsumoto" } } ).explain(); 
# 内嵌文档索引必须内嵌文档里面的内容完全匹配才能查出,所以这就是上面的查询为什么只返回了一条数据的理由  

#没有使用索引    查询到了数据(两条数据都查到了)
db.user.find(
   {
     "name.first": "Yukihiro",
     "name.last": "Matsumoto"
   }
).explain();

 

     内嵌文档索引

#建立索引前查询
db.collection.find({"contents.content":"传统美术"}).explain()
#建立索引
db.collection.ensureIndex({ "contents.content": 1} )
#建立索引后查询
db.collection.find({"contents.content":"传统美术"}).explain()

#建立索引前查询
db.collection.find({"contents":{$elemMatch:{"fieldId":"project_type","content":"传统美术"}}}).explain()
#建立索引
db.collection.ensureIndex({ "contents.fieldId": 1,"contents.content": 1} )
#建立索引后查询
db.collection.find({"contents":{$elemMatch:{"fieldId":"project_type","content":"传统美术"}}}).explain()
#建立索引后性能有了明显的提升。

 

 

    5、唯一索引  {unique:true}

        db.collection.ensureIndex({"name":1},{unique:true})    为collection的name属性创建正序唯一索引

    6、全文索引

        当前数据库开启全文索引:db.adminCommand({setParameter:true,textSearchEnabled:true})

        新建全文索引:db.collection.ensureIndex({"contents.content":"text"});

        使用全文索引进行查询:db.collection.find({$text:{$search:"景区"}})

        参考文章:http://www.ziqiangxuetang.com/mongodb/mongodb-text-search.html

        注意:一张表只能新建一个全文索引。

   7、哈希索引 {'field':'hashed'}

        哈希索引特点:速度比普通索引块,但是无法对范围查询进行优化。哈希索引不适合范围查询,哈希索引只支持单字段的索引,不支持多字段索引。

         新建哈希索引:db.collection.ensureIndex({"createTime":"hashed"});

   8、后台索引

        db.people.ensureIndex({zipcode:1},{background:true})

         后台索引不会像其它索引一样,不是个阻塞操作。

   9、稀疏索引   { sparse: true }

    稀疏索引的特点:如果针对field做索引,针对不含field列的文档将不建立索引。

 

#准备数据
db.user2.insert({'name':'zhangsan'});
db.user2.insert({'name':'lisi'});
db.user2.insert({});

db.user2.find({'name':null});

#唯一索引测试
db.user2.ensureIndex({"name":1},{unique: true})
db.user2.find({'name':null}).explain();  #使用了索引
db.user2.find({'name':'zhangsan'}).explain(); #使用了索引
db.user2.dropIndexes();


db.user2.ensureIndex({"name":1},{sparse: true})
db.user2.find({'name':null}).explain();  #没有使用索引
db.user2.find({'name':'zhangsan'}).explain(); #使用了索引

    注意:db.user2.find({'name':null}).explain();  #没有使用索引,这是稀疏索引和其它索引的区别

 

   10、地理位置坐标索引

       xxxxxx

 

 

 参考文章:http://www.jb51.net/article/39671.htm

                   http://www.cnblogs.com/Amaranthus/p/3574058.html#_Toc381385679

三、建立索引的原则

 

   1、创建的索引要匹配查询

如果你仅仅要查询单个字段。索引这个字段即可。如
db.user.find({"account":"zhangsan"})
这个例子中,唯一索引是最佳的
db.user.ensureIndex({"account":1 }, {unique: true});

   

然而,一般都查询多个键并且排序结果。这种情况,组合索引是最佳的,例子如下
db.project_material.find({ provinceId : '66ef8bd44b3a4a8d6a819120'}).sort({ createTime : -1 });
创建的索引如下
db.project_material.ensureIndex({provinceId : 1, createTime : -1});

 

2、索引列颗粒越小越好

 

3、要小心单键索引的低选择性。

 

4、要关注应用读/写( read/write) 比率,不要随意添加索引

这个很重要,因为,添加索引意味着添加,更新,删除操作变慢。

如果你的应用是偏向于读取,使用索引是非常好的事情。

 

5、先后顺序不一样,效果也不一样

db.item_file.ensureIndex({"displayOrder":1,"itemTitle":1,"itemCode":1});不等于下面的

db.item_file.ensureIndex({"itemTitle":1,"itemCode":1,"displayOrder":1});

 

 

 

参考文章:http://www.2cto.com/os/201501/369209.html

 

索引如何设计(读取场景相应的索引设计)

1,查询返回某些字段,而这些字段都可以放在索引中时

  索引覆盖查询,

  这样做的好处是MongoDB就没有必要加载整个文档,通过索引就可以搞定。

2,联合查询

   支持前缀索引查询。

MongoDB有个特性:不是前缀查询无法利用索引。

3,查询返回数据占文档集合数据的比重很大时

   不建立索引查询会更快。

   比如文档200G  索引50G

   使用索引就必须加载到内存250G,如果不使用索引全表扫描 加载到内存只有200G 反而更快。

4,不要到处使用索引,索引的使用要适中。

返回数据量小的文档,建议使用索引。

返回>=50%文档数据时,不建议使用索引

 

 

四、性能比较

已建立索引和未建索引前后插入效率对比:

var start =new Date();
for(var i=0;i<100000;i++){
	db.log_login_copy1.insert({"user":"ceshi"+i,"fromIP":"113.91.248.225","memo" : "成功登录","logLevel" : "INFO","logModel" : "浏览器"+i});
}
var end = new Date();
print("建了索引插入10万行数据耗时="+(end-start));

 

 

 

var start =new Date();
for(var i=0;i<100000;i++){
	db.log_login_copy2.insert({"user":"ceshi"+i,"fromIP":"113.91.248.225","memo" : "成功登录","logLevel" : "INFO","logModel" : "浏览器"+i});
}
var end = new Date();
print("没建索引插入10万行数据耗时="+(end-start));

 

 

总结:

插入的速度没有网上说的那么快只要三秒左右,为什么呢?

已经建立索引和未建立索引的查询效率差异不大 实际是这样吗?

 

已建立索引和未建索引前后查询效率对比:

查询语句

db.log_login.find({"user":"qinghai"}).explain()

 

建立索引的语句

db.log_login.ensureIndex({"user":1})

  

 没有建立索引查询耗时(总共100万行记录):

 

建立索引后查询耗时(总共100万行记录):

 

 

explain用法: 查看查询计划

  explain()是非常有用的工具,会帮助你获得查询方面诸多有用的信息。只要对游标调用该方法,就可以得到查询细节

  eg:db.role.find().explain()

 

 字段说明:
    cursor:返回游标类型,有BasicCursor和BtreeCursor,后者意味着使用了索引。
    nscanned:扫描document的行数。
    n:返回的文档行数。
    millis:耗时(毫秒)。这个对于比较索引和非索引性能非常有用。
indexBounds:所用的索引。

 


 总结:从上面两幅截图对比可以看出创建索引后速度提升了上百倍

 

问题:

模糊查询为什么使用了索引效率还是非常低下呢?201604  查询用了指定新建的索引后效率至少降低了一半,有什么解决方法吗?   是优化模糊查询的方式解决,还是建立其它索引的方式解决,还是没有解决方法呢?

 

常见错误:

1,Btree::insert: key too large to index 内容太多不能新建索引。

解决方法:在当前数据库下执行下面命令:db.adminCommand({setParameter:true,failIndexKeyTooLong:false});

 

 2,如果执行查询报下面错误

com.mongodb.MongoException: Runner error: Overflow sort stage buffered data usage of 33555102 bytes exceeds internal limit of 33554432 bytes

那提取出查询语句:

db.item_file.find({ "itemTitle" : { "$regex" : "^.*?.*$" , "$options" : "i"} , "itemCode" : { "$regex" : "^.*?.*$" , "$options" : "i"}}).sort({ "displayOrder" : 1}).skip(58860).limit(10);

新建下面索引:

db.item_file.ensureIndex({"displayOrder":1});

但是为什么不是新建下面的索引呢? 20160321.  后面有时间的时候查查。

db.item_file.ensureIndex({"itemTitle":1,"itemCode":1,"displayOrder":1});

新建下面这个索引是可以的。

db.item_file.ensureIndex({"displayOrder":1,"itemTitle":1,"itemCode":1});

 

 

 

 

 

 

 

  

  • 大小: 6.5 KB
  • 大小: 6.6 KB
  • 大小: 25.8 KB
  • 大小: 28.7 KB
分享到:
评论

相关推荐

    MongoDB数据库索引介绍.pptx

    ### 每个 index 都应该被查询使用,定期检查无用索引 每个索引都应该被查询使用,否则将会浪费资源。定期检查无用索引可以减少资源浪费。 结论 ---------- MongoDB 数据库索引是提高查询性能和减少查询时间的重要...

    MONGODB的索引探究

    MongoDB的索引是数据库性能优化的关键因素,与MySQL、Oracle等关系型数据库中的索引原理相似,但具有自身的特性和限制。MongoDB的索引建立在Collection(表)级别,采用B-树数据结构来加速查询和排序操作。 1. 默认...

    MongoDB学习笔记(六) MongoDB索引用法和效率分析

    MongoDB是一种流行的NoSQL数据库,它的索引机制与传统的关系型数据库类似,旨在提升查询和排序的速度。在MongoDB中,索引对于优化查询性能至关重要,尤其在处理大量数据时。下面将详细介绍MongoDB中不同类型的索引...

    MongoDB索引管理.pdf

    在 MongoDB 中,索引管理是优化查询性能的关键环节。以下是对 MongoDB 索引管理的深入探讨: 1. **查看索引** MongoDB 提供了多种方法来查看已创建的索引。通过 `getIndexes()` 方法,你可以获取到指定集合上的...

    MongoDB索引管理与高级索引.pdf

    本篇文章将详细探讨MongoDB中的索引管理以及高级索引概念。 1. **查看索引** MongoDB 提供了两种方法来查看集合上的索引。`db.COLLECTION_NAME.getIndexes()` 方法返回集合上所有索引的详细信息,而 `db.system....

    SpringBoot MongoDB 索引冲突分析及解决方法

    1. 删除已经存在的索引:可以使用 MongoDB 的命令来删除已经存在的索引,例如,使用 db.collection.dropIndex() 命令来删除索引。 2. 重新创建索引:可以使用 MongoDB 的命令来创建新的索引,例如,使用 db....

    MongoDB索引与查询.pdf

    索引是 MongoDB 中的关键概念,它们能够显著提升查询性能。本篇资料主要涵盖了 MongoDB 的索引使用和查询分析,以下是对这些知识点的详细解释: 1. **explain操作**:`explain` 是 MongoDB 提供的一个命令,用于...

    mongodb搭建,shell操作,索引,副本集

    #### MongoDB索引 - **介绍**:索引能够显著提高查询性能,MongoDB支持单字段索引、复合索引、唯一索引等多种类型的索引。 - **后台创建索引**:可以在运行时创建索引,而无需停止服务。 - **索引类型**: - **单...

    MongoDB索引使用详解

    MongoDB索引是数据库性能优化的关键工具,它们类似于书籍的目录,可以帮助快速定位到所需的数据,从而大大提高查询效率。在没有索引的情况下,MongoDB必须遍历整个集合来找到匹配的文档,这在数据量大的时候会导致...

    MongoDB 索引 和explain分析查询速度1

    索引是提升查询性能的关键工具,本文将详细介绍MongoDB中的索引基础知识、唯一索引、索引参数以及如何通过`explain`分析查询速度。 一、索引基础 在MongoDB中,索引是一种特殊的数据结构,它们对集合中的一列或多...

    Mongodb索引的优化

    在MongoDB中,索引扮演着至关重要的角色,它类似于传统的关系型数据库,通过B-Tree数据结构加速数据查找和排序。 ### 一、索引简介 MongoDB 的索引可以通过`ensureIndex()`函数创建,指定一个或多个字段来提升查询...

    index-model:MongoDB索引模型

    mongodb-index-model 适用于人类的MongoDB索引工具包。例子var IndexModel = require ( 'mongodb-index-model' ) ;// e.g. from collection.getIndexes()var indexDefs = [ { 'v' : 1 , 'key' : { '_id' : 1 } , '...

    MongoDB数据库中索引(index)详解

    MongoDB数据库中的索引是提升查询效率的关键工具,它们是一种特殊的数据结构,用于存储表中数据的一小部分,以加速数据检索。索引的优点主要体现在减少服务器扫描的数据量、帮助服务器避免排序或使用临时表以及将...

    关于MongoDB索引管理-索引的创建、查看、删除操作详解

    - **删除索引**:MongoDB 提供了 `dropIndexes()` 或 `dropIndex()` 方法来删除索引。`dropIndexes()` 会删除集合的所有索引,而 `dropIndex()` 允许指定要删除的索引名称。例如,`db.COLLECTION_NAME.dropIndexes...

    MongoDB索引实战技巧

    主要描述了MongoDB索引相关的一些基础知识和使用技巧。 虽然MongoDB的索引在存储结构上都是一样的,但是根据不同的应用层需求,还是分成了唯一索引(unique)、稀疏索引(sparse)、多值索引(multikey)等几种类型...

    pymongo为mongodb数据库添加索引的方法

    本文实例讲述了pymongo为mongodb数据库添加索引的方法。分享给大家供大家参考。具体实现方法如下: ... 您可能感兴趣的文章:MongoDB索引使用详解MongoDB的基础查询和索引操作方法总结pymongo给mongodb创建索

    MongoDB-索引

    索引是数据库系统中提升查询性能的关键机制,MongoDB 的索引设计与传统关系型数据库类似,但也有其独特之处。 一、索引基础 1. 创建索引:在 MongoDB 中,你可以通过 `ensureIndex` 命令来创建索引,例如创建一个...

Global site tag (gtag.js) - Google Analytics