热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:练习MongoDB操作——索引篇

篇首语:本文由编程笔记#小编为大家整理,主要介绍了练习MongoDB操作——索引篇相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了练习 MongoDB 操作 —— 索引篇相关的知识,希望对你有一定的参考价值。




目录




  • Mongodb 索引篇(二)

  • 索引

    • 操作

      • 创建索引

      • 查看索引

      • 删除索引


    • 唯一索引

    • 稀疏索引

    • 性能示例


  • 游标




Mongodb 索引篇(二)

技术图片 mongodb

更新于 2017-09-19 约 11 分钟

原文链接:https://segmentfault.com/a/1190000011263553

本文围绕索引、游标两部分进行探索,对MongoDB数据库的索引部分有一个大概的了解;


索引

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。

索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。索引,从创建的形式上可以分为普通索引复合索引数组索引子文档索引

应该了解的索引限制,



  • 开销:每个索引占据一定的存储空间,在进行插入,更新和删除操作时也需要对索引进行操作。所以,如果你很少对集合进行读取操作,建议不使用索引;


  • 内存(RAM)使用:由于索引是存储在内存中,你应该确保该索引的大小不超过内存的限制。如果索引的大小大于内存的限制,MongoDB会删除一些索引,这将导致性能下降。


  • 最大范围:

    (1)集合中索引不能超过 64 个;
    (2)索引名的长度不能超过 125 个字符;
    (3)一个复合索引最多可以有 31 个字段


  • 索引不能被以下的查询使用;可以调用explain()方法查看是否使用索引;

    (1)正则表达式及非操作符,如 `$nin`, `$not`, 等
    (2)算术运算符,如 `$mod` 等
    (3)`$where` 子句



操作


创建索引

为集合grade_1_4根据性别和年龄创建复合索引:

db.getCollection('grade_1_4').ensureIndex({"sex": 1, "age": 1})

会得到结果:

{
"v" : 2, // 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本
"key" : {
"sex" : 1,
"age" : 1
},
"name" : "sex_1_age_1",
"ns" : "school.grade_1_4"
}

说明:基于sexage的查询将会用到该复合索引,或者是基于sex的查询也会用到该索引,但是只是基于age的查询将不会用到该复合索引。因此可以说,如果想用到复合索引,必须在查询条件中包含复合索引中的前N个索引列。然而如果查询条件中的键值顺序和复合索引中的创建顺序不一致的话,MongoDB可以智能的帮助我们调整该顺序,以便使复合索引可以为查询所用


如果分别为性别和年龄创建索引:

db.getCollection('grade_1_4').ensureIndex({"sex": 1})
db.getCollection('grade_1_4').ensureIndex({"age": 1})

会得到这样的结果:

{
"v" : 2,
"key" : {
"sex" : 1
},
"name" : "sex_1",
"ns" : "school.grade_1_4"
},
{
"v" : 2,
"key" : {
"age" : 1
},
"name" : "age_1",
"ns" : "school.grade_1_4"
}

查看索引

查看集合grade_1_4已经创建的索引规则:

db.getCollection('grade_1_4').getIndexes()

查看集合grade_1_4索引占用内存空间的大小,单位是字节:

db.getCollection('grade_1_4').totalIndexSize()

删除索引

删除集合grade_1_4namesex_1的索引规则:

db.getCollection('grade_1_4').dropIndex({"sex": 1})

唯一索引

创建唯一索引与普通索引的区别在于,多一个可选参数 unique;举个例子,根据姓名创建唯一索引:

db.getCollection('grade_1_4').ensureIndex({"name":1}, {"unique":true})

创建唯一索引能够保证每条记录的name字段值是不重复的;

当一个文档以唯一索引的方式保存到集合中去的时候,任何缺失的索引字段都会以null值代替,因此,不能在唯一索引上同时插入两条缺省的记录。

假设集合已经存在一些记录,在些基础上创建唯一索引;此时,对这些已经存在的记录,如果索引项值是存在重复的,则创建索引时会报错;如果一定要在这样的键上创建唯一索引,那么系统将保存第一条记录,剩下的记录会被删除,结合dropDups参数使用(此参数只能在mongodb 3.0版本之前使用):

db.getCollection('grade_1_4').ensureIndex({"name":1}, {unique:true, dropDups: true})

稀疏索引

稀疏索引的创建和完全索引的创建没有什么不同。使用稀疏索引进行查询的时候,某些由于缺失了字段的文档记录可能不会被返回,这是由于稀疏索引子返回被索引了的字段。

示例:

> db.people.ensureIndex({title:1},{sparse:true}) //在title字段上建立稀疏索引
> db.people.save({name:"Jim"})
> db.people.save({name:"yang",title:"prince"})
> db.people.find();
{ "_id" : ObjectId("4e244dc5cac1e3490b9033d7"), "name" : "Jim" }
{ "_id" : ObjectId("4e244debcac1e3490b9033d8"), "name" : "yang", "title" : "prince" }
> db.people.find().sort({title:1})//自有包含有索引字段的记录才被返回
{ "_id" : ObjectId("4e244debcac1e3490b9033d8"), "name" : "yang", "title" : "prince" }
> db.people.dropIndex({title:1})//删除稀疏索引之后,所有的记录均显示
{ "nIndexesWas" : 2, "ok" : 1 }
> db.people.find().sort({title:1})
{ "_id" : ObjectId("4e244dc5cac1e3490b9033d7"), "name" : "Jim" }
{ "_id" : ObjectId("4e244debcac1e3490b9033d8"), "name" : "yang", "title" : "prince" }

性能示例

创建三十万条数据

for (var i = 1; i <= 300000; i++) {
db.getCollection(&#39;grade_1_5&#39;).insert({
"name": "zhangsan" + i,
"sex": Math.round(Math.random() * 10) % 2,
"age": Math.round(Math.random() * 6) + 3
});
}

根据姓名查一些特定的人

db.getCollection(&#39;grade_1_5&#39;).find(
{
$or: [{"name":"zhangsan10000"},{"name":"zhangsan14000"},{"name":"zhangsan9000"},{"name":"zhangsan23000"},{"name":"zhangsan24050"},
{"name":"zhangsan12000"},{"name":"zhangsan14300"},{"name":"zhangsan9300"},{"name":"zhangsan23300"},{"name":"zhangsan24350"},
{"name":"zhangsan11100"},{"name":"zhangsan15200"},{"name":"zhangsan8100"},{"name":"zhangsan22100"},{"name":"zhangsan26150"},
{"name":"zhangsan10200"},{"name":"zhangsan14020"},{"name":"zhangsan9020"},{"name":"zhangsan23020"},{"name":"zhangsan24070"},
{"name":"zhangsan10300"},{"name":"zhangsan14030"},{"name":"zhangsan9030"},{"name":"zhangsan23030"},{"name":"zhangsan24080"}]
}
)

对姓名建立索引,会占用5873664字节

db.getCollection(&#39;grade_1_5&#39;).ensureIndex({"name": 1})

对于上面的命令,通过调整顺序,观察时间,对性能有一些大概的了解;































行为创建-查询-建索引创建-建索引-查询建索引-创建-查询
创建时间150.957s150.957s159.967s
查询时间1.024s0.005s0.005s
建立索引时间0.527s0.527s0.009s

游标

直接对一个集合调用find()方法时,我们会发现,如果查询结果超过二十条,只会返回二十条的结果,这是因为Mongodb会自动递归find()返回的是游标。

var cursor = db.getCollection(&#39;grade_1_4&#39;).find({});

执行上述命令时,shell并不会真正地访问数据库,而是等待开始要求获得结果的时候才向数据库发送查询请求。

此时可以对这个游标进行各种设置,然后调用游标的hashNext()next()方法,这样就会真正访问数据库,这是一个懒加载的过程,如下

var cursor = db.getCollection(&#39;grade_1_4&#39;).find({});
while(cursor.hasNext()){
var doc = cursor.next();
// do stuff with doc
};

可以基于游标,进行limit、skip、sort操作,一般应用于分页场景;



  • limit:限制游标返回的数量,指定了上限;

  • skip :忽略前面的部分文档,如果文档总数量小于忽略的数量,则返回空集合;

  • sort :对得到的子集合进行排序,可以按照多个键进行正反排序;

上述三个命令可以进行链式操作;

文章来源于网络,仅用于学习,如有侵权,请联系删除。


推荐阅读
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 开发笔记:Java是如何读取和写入浏览器Cookies的
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java是如何读取和写入浏览器Cookies的相关的知识,希望对你有一定的参考价值。首先我 ... [详细]
  • Oracle seg,V$TEMPSEG_USAGE与Oracle排序的关系及使用方法
    本文介绍了Oracle seg,V$TEMPSEG_USAGE与Oracle排序之间的关系,V$TEMPSEG_USAGE是V_$SORT_USAGE的同义词,通过查询dba_objects和dba_synonyms视图可以了解到它们的详细信息。同时,还探讨了V$TEMPSEG_USAGE的使用方法。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
author-avatar
13578945682a_699
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有