一、索引的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});
相关推荐
### 每个 index 都应该被查询使用,定期检查无用索引 每个索引都应该被查询使用,否则将会浪费资源。定期检查无用索引可以减少资源浪费。 结论 ---------- MongoDB 数据库索引是提高查询性能和减少查询时间的重要...
MongoDB的索引是数据库性能优化的关键因素,与MySQL、Oracle等关系型数据库中的索引原理相似,但具有自身的特性和限制。MongoDB的索引建立在Collection(表)级别,采用B-树数据结构来加速查询和排序操作。 1. 默认...
MongoDB是一种流行的NoSQL数据库,它的索引机制与传统的关系型数据库类似,旨在提升查询和排序的速度。在MongoDB中,索引对于优化查询性能至关重要,尤其在处理大量数据时。下面将详细介绍MongoDB中不同类型的索引...
在 MongoDB 中,索引管理是优化查询性能的关键环节。以下是对 MongoDB 索引管理的深入探讨: 1. **查看索引** MongoDB 提供了多种方法来查看已创建的索引。通过 `getIndexes()` 方法,你可以获取到指定集合上的...
本篇文章将详细探讨MongoDB中的索引管理以及高级索引概念。 1. **查看索引** MongoDB 提供了两种方法来查看集合上的索引。`db.COLLECTION_NAME.getIndexes()` 方法返回集合上所有索引的详细信息,而 `db.system....
1. 删除已经存在的索引:可以使用 MongoDB 的命令来删除已经存在的索引,例如,使用 db.collection.dropIndex() 命令来删除索引。 2. 重新创建索引:可以使用 MongoDB 的命令来创建新的索引,例如,使用 db....
索引是 MongoDB 中的关键概念,它们能够显著提升查询性能。本篇资料主要涵盖了 MongoDB 的索引使用和查询分析,以下是对这些知识点的详细解释: 1. **explain操作**:`explain` 是 MongoDB 提供的一个命令,用于...
#### MongoDB索引 - **介绍**:索引能够显著提高查询性能,MongoDB支持单字段索引、复合索引、唯一索引等多种类型的索引。 - **后台创建索引**:可以在运行时创建索引,而无需停止服务。 - **索引类型**: - **单...
MongoDB索引是数据库性能优化的关键工具,它们类似于书籍的目录,可以帮助快速定位到所需的数据,从而大大提高查询效率。在没有索引的情况下,MongoDB必须遍历整个集合来找到匹配的文档,这在数据量大的时候会导致...
索引是提升查询性能的关键工具,本文将详细介绍MongoDB中的索引基础知识、唯一索引、索引参数以及如何通过`explain`分析查询速度。 一、索引基础 在MongoDB中,索引是一种特殊的数据结构,它们对集合中的一列或多...
在MongoDB中,索引扮演着至关重要的角色,它类似于传统的关系型数据库,通过B-Tree数据结构加速数据查找和排序。 ### 一、索引简介 MongoDB 的索引可以通过`ensureIndex()`函数创建,指定一个或多个字段来提升查询...
mongodb-index-model 适用于人类的MongoDB索引工具包。例子var IndexModel = require ( 'mongodb-index-model' ) ;// e.g. from collection.getIndexes()var indexDefs = [ { 'v' : 1 , 'key' : { '_id' : 1 } , '...
MongoDB数据库中的索引是提升查询效率的关键工具,它们是一种特殊的数据结构,用于存储表中数据的一小部分,以加速数据检索。索引的优点主要体现在减少服务器扫描的数据量、帮助服务器避免排序或使用临时表以及将...
- **删除索引**:MongoDB 提供了 `dropIndexes()` 或 `dropIndex()` 方法来删除索引。`dropIndexes()` 会删除集合的所有索引,而 `dropIndex()` 允许指定要删除的索引名称。例如,`db.COLLECTION_NAME.dropIndexes...
主要描述了MongoDB索引相关的一些基础知识和使用技巧。 虽然MongoDB的索引在存储结构上都是一样的,但是根据不同的应用层需求,还是分成了唯一索引(unique)、稀疏索引(sparse)、多值索引(multikey)等几种类型...
本文实例讲述了pymongo为mongodb数据库添加索引的方法。分享给大家供大家参考。具体实现方法如下: ... 您可能感兴趣的文章:MongoDB索引使用详解MongoDB的基础查询和索引操作方法总结pymongo给mongodb创建索
索引是数据库系统中提升查询性能的关键机制,MongoDB 的索引设计与传统关系型数据库类似,但也有其独特之处。 一、索引基础 1. 创建索引:在 MongoDB 中,你可以通过 `ensureIndex` 命令来创建索引,例如创建一个...